diff --git a/.github/lock.yml b/.github/lock.yml index 974f87a3..a1d7e6e1 100644 --- a/.github/lock.yml +++ b/.github/lock.yml @@ -30,13 +30,7 @@ lockLabel: false # Comment to post before locking. Set to `false` to disable -lockComment: > - - This thread has been automatically locked since there has not been - - any recent activity after it was closed. Please open a new issue for - - related bugs. +lockComment: false diff --git a/.gitignore b/.gitignore index e0a67323..89b121a8 100644 --- a/.gitignore +++ b/.gitignore @@ -33,4 +33,5 @@ crowdinstats.csv *.iml .vscode/.BROWSE.VC.DB-shm .vscode/.BROWSE.VC.DB-wal -package-lock.json \ No newline at end of file +package-lock.json +.DS_Store \ No newline at end of file diff --git a/docs/examples/rando.md b/docs/examples/rando.md index 009807ee..00670ad5 100644 --- a/docs/examples/rando.md +++ b/docs/examples/rando.md @@ -4,6 +4,6 @@ Generate a random coordinate and display it on the LED screen. ```blocks basic.forever(() => { - led.toggle(Math.randomRange(0, 5), Math.randomRange(0, 5)) + led.toggle(Math.randomRange(0, 4), Math.randomRange(0, 4)) }) ``` \ No newline at end of file diff --git a/docs/projects/love-meter.md b/docs/projects/love-meter.md index 84e25a75..37fbc01b 100644 --- a/docs/projects/love-meter.md +++ b/docs/projects/love-meter.md @@ -3,7 +3,6 @@ ## Introduction @unplugged Make a love meter, how sweet! The @boardname@ is feeling the love, then sometimes not so much! -Tell everyone who you are. Show you name on the LEDs. ![Love meter banner message](/calliope/tutorials/05_love_meter_animation.gif) diff --git a/docs/projects/snap-the-dot.md b/docs/projects/snap-the-dot.md index 715c7260..5d3a0f55 100644 --- a/docs/projects/snap-the-dot.md +++ b/docs/projects/snap-the-dot.md @@ -8,13 +8,19 @@ Snap the dot is a game of skill where the player has to press **A** exactly when This tutorial shows how to use the game engine. -## Create a sprite @fullscreen +## Make a sprite variable @fullscreen -Drag a ``||game:create sprite||`` block onto the workspace. A sprite is a single pixel that can move on the screen. It has an ``x`` and ``y`` position along with a direction of motion. +Create a new variable called `sprite`. Drag a ``||variables:set sprite to||`` into the ``||basic:on start||`` on the workspace. ```blocks -let sprite: game.LedSprite = null -sprite = game.createSprite(2, 2) +let sprite = 0 +``` +## Create a sprite @fullscreen + +Pull out a ``||game:create sprite||`` block and put it in ``||variables:set sprite to||`` replacing the `0`. A sprite is a single pixel that can move on the screen. It has an ``x`` and ``y`` position along with a direction of motion. + +```blocks +let sprite = game.createSprite(2, 2) ``` ## Move the dot @fullscreen @@ -22,8 +28,7 @@ sprite = game.createSprite(2, 2) The sprite starts in the center facing right. Put a ``||game:move||`` block into the ``||basic:forever||`` to make it move. Notice how it moves to the right but does not bounce back. ```blocks -let sprite: game.LedSprite = null -sprite = game.createSprite(2, 2) +let sprite = game.createSprite(2, 2) basic.forever(function () { sprite.move(1) }) @@ -34,8 +39,7 @@ basic.forever(function () { Grab a ``||game:if on edge, bounce||`` block to make the sprite bounce on the side of the screen. Also, add a ``||basic:pause||`` block to slow down the sprite. ```blocks -let sprite: game.LedSprite = null -sprite = game.createSprite(2, 2) +let sprite = game.createSprite(2, 2) basic.forever(function () { sprite.move(1) sprite.ifOnEdgeBounce() @@ -54,13 +58,12 @@ When **A** is pressed, we test if the sprite is in the center or not. Use a ``||input:on button pressed||`` block to handle the **A** button. Put in a ``||logic:if||`` block and test if ``||game:x||`` is equal to `2`. ```blocks -let sprite: game.LedSprite = null +let sprite = game.createSprite(2, 2) input.onButtonPressed(Button.A, function () { if (sprite.get(LedSpriteProperty.X) == 2) { } else { } }) -sprite = game.createSprite(2, 2) basic.forever(function () { sprite.move(1) basic.pause(100) @@ -73,7 +76,7 @@ basic.forever(function () { Finally, pull out an ``||game:add score||`` and a ``||game:game over||`` block to handle both success (sprite in the center) and failure (sprite not in the center). ```blocks -let sprite: game.LedSprite = null +let sprite = game.createSprite(2, 2) input.onButtonPressed(Button.A, function () { if (sprite.get(LedSpriteProperty.X) == 2) { game.addScore(1) @@ -81,7 +84,6 @@ input.onButtonPressed(Button.A, function () { game.gameOver() } }) -sprite = game.createSprite(2, 2) basic.forever(function () { sprite.move(1) basic.pause(100) diff --git a/docs/reference/led/plot-bar-graph.md b/docs/reference/led/plot-bar-graph.md index e64fbee5..cb5bd645 100644 --- a/docs/reference/led/plot-bar-graph.md +++ b/docs/reference/led/plot-bar-graph.md @@ -17,6 +17,15 @@ A bar graph is a kind of chart that shows numbers as lines with different length * **high**: a [number](/types/number) that is the highest possible number (maximum) that the **value** parameter can be. The lines in the bar graph will reach their highest point when **value** reaches this number. If **high** is `0`, then the largest value recently plotted is used as the maximum. +### ~hint + +#### Serial Output + +The ``||led:plot bar graph||`` block also writes the number from **value** to the [serial](/reference/serial) port as a way to help you record +values. + +### ~ + ## Example: chart acceleration Show a bar graph of the [acceleration](/reference/input/acceleration) diff --git a/docs/static/configurations/chrome-version.png b/docs/static/configurations/chrome-version.png new file mode 100644 index 00000000..b7a4db67 Binary files /dev/null and b/docs/static/configurations/chrome-version.png differ diff --git a/docs/static/configurations/edge-version.png b/docs/static/configurations/edge-version.png new file mode 100644 index 00000000..f9c9095a Binary files /dev/null and b/docs/static/configurations/edge-version.png differ diff --git a/docs/static/configurations/firefox-version.png b/docs/static/configurations/firefox-version.png new file mode 100644 index 00000000..d9b5684c Binary files /dev/null and b/docs/static/configurations/firefox-version.png differ diff --git a/docs/static/configurations/ie-version.png b/docs/static/configurations/ie-version.png new file mode 100644 index 00000000..3fbc6e7c Binary files /dev/null and b/docs/static/configurations/ie-version.png differ diff --git a/docs/static/configurations/osx-version.png b/docs/static/configurations/osx-version.png new file mode 100644 index 00000000..9457d7e4 Binary files /dev/null and b/docs/static/configurations/osx-version.png differ diff --git a/docs/static/configurations/safari-version.png b/docs/static/configurations/safari-version.png new file mode 100644 index 00000000..70d1d871 Binary files /dev/null and b/docs/static/configurations/safari-version.png differ diff --git a/docs/static/configurations/windows-version.png b/docs/static/configurations/windows-version.png new file mode 100644 index 00000000..06847ede Binary files /dev/null and b/docs/static/configurations/windows-version.png differ diff --git a/libs/core/_locales/core-jsdoc-strings.json b/libs/core/_locales/core-jsdoc-strings.json index d86dc4e6..d43084a7 100644 --- a/libs/core/_locales/core-jsdoc-strings.json +++ b/libs/core/_locales/core-jsdoc-strings.json @@ -89,8 +89,8 @@ "Gesture.FreeFall": "Raised when the board is falling!", "Gesture.LogoDown": "Raised when the logo is downward and the screen is vertical", "Gesture.LogoUp": "Raised when the logo is upward and the screen is vertical", - "Gesture.ScreenDown": "Raised when the screen is pointing up and the board is horizontal", - "Gesture.ScreenUp": "Raised when the screen is pointing down and the board is horizontal", + "Gesture.ScreenDown": "Raised when the screen is pointing down and the board is horizontal", + "Gesture.ScreenUp": "Raised when the screen is pointing up and the board is horizontal", "Gesture.Shake": "Raised when shaken", "Gesture.SixG": "Raised when a 6G shock is detected", "Gesture.ThreeG": "Raised when a 3G shock is detected", @@ -273,6 +273,8 @@ "control.eventValue": "Gets the value of the last event executed on the bus", "control.eventValueId": "Returns the value of a C++ runtime constant", "control.inBackground": "Schedules code that run in the background.", + "control.micros": "Gets current time in microseconds. Overflows every ~18 minutes.", + "control.millis": "Gets the number of milliseconds elapsed since power on.", "control.onEvent": "Registers an event handler.", "control.panic": "Display specified error code and stop the program.", "control.raiseEvent": "Raises an event in the event bus.", @@ -281,6 +283,7 @@ "control.raiseEvent|param|value": "Component specific code indicating the cause of the event.", "control.reset": "Resets the BBC micro:bit.", "control.runtimeWarning": "Display warning in the simulator.", + "control.waitForEvent": "Blocks the calling thread until the specified event is raised.", "control.waitMicros": "Blocks the current fiber for the given microseconds", "control.waitMicros|param|micros": "number of micro-seconds to wait. eg: 4", "convertToText": "Convert any value to text", @@ -467,9 +470,13 @@ "music.builtInMelody": "Gets the melody array of a built-in melody.", "music.changeTempoBy": "Change the tempo by the specified amount", "music.changeTempoBy|param|bpm": "The change in beats per minute to the tempo, eg: 20", + "music.melodyEditor": "Create a melody with the melody editor.", "music.noteFrequency": "Get the frequency of a note.", "music.noteFrequency|param|name": "the note name, eg: Note.C", "music.onEvent": "Registers code to run on various melody events", + "music.playMelody": "Play a melody from the melody editor.", + "music.playMelody|param|melody": "- string of up to eight notes [C D E F G A B C5] or rests [-] separated by spaces, which will be played one at a time, ex: \"E D G F B A C5 B \"", + "music.playMelody|param|tempo": "- number in beats per minute (bpm), dictating how long each note will play for", "music.playTone": "Plays a tone through pin ``P0`` for the given duration.", "music.playTone|param|frequency": "pitch of the tone to play in Hertz (Hz), eg: Note.C", "music.playTone|param|ms": "tone duration in milliseconds (ms)", diff --git a/libs/core/_locales/core-strings.json b/libs/core/_locales/core-strings.json index 4ecc562e..801407b1 100644 --- a/libs/core/_locales/core-strings.json +++ b/libs/core/_locales/core-strings.json @@ -79,9 +79,9 @@ "Gesture.LogoDown|block": "logo down", "Gesture.LogoUp": "Raised when the logo is upward and the screen is vertical", "Gesture.LogoUp|block": "logo up", - "Gesture.ScreenDown": "Raised when the screen is pointing up and the board is horizontal", + "Gesture.ScreenDown": "Raised when the screen is pointing down and the board is horizontal", "Gesture.ScreenDown|block": "screen down", - "Gesture.ScreenUp": "Raised when the screen is pointing down and the board is horizontal", + "Gesture.ScreenUp": "Raised when the screen is pointing up and the board is horizontal", "Gesture.ScreenUp|block": "screen up", "Gesture.Shake": "Raised when shaken", "Gesture.Shake|block": "shake", @@ -262,9 +262,11 @@ "control.eventValueId|block": "%id", "control.eventValue|block": "event value", "control.inBackground|block": "run in background", + "control.millis|block": "millis (ms)", "control.onEvent|block": "on event|from %src=control_event_source_id|with value %value=control_event_value_id", "control.raiseEvent|block": "raise event|from source %src=control_event_source_id|with value %value=control_event_value_id", "control.reset|block": "reset", + "control.waitForEvent|block": "wait for event|from %src|with value %value", "control.waitMicros|block": "wait (µs)%micros", "control|block": "control", "convertToText|block": "convert $value=math_number to text", @@ -338,8 +340,10 @@ "music.beginMelody|block": "start melody %melody=device_builtin_melody| repeating %options", "music.builtInMelody|block": "%melody", "music.changeTempoBy|block": "change tempo by (bpm)|%value", + "music.melodyEditor|block": "$melody", "music.noteFrequency|block": "%name", "music.onEvent|block": "music on %value", + "music.playMelody|block": "play melody $melody at tempo $tempo|(bpm)", "music.playTone|block": "play|tone %note=device_note|for %duration=device_beat", "music.rest|block": "rest(ms)|%duration=device_beat", "music.ringTone|block": "ring tone (Hz)|%note=device_note", diff --git a/libs/core/control.cpp b/libs/core/control.cpp index 0aff221f..c40c8bc6 100644 --- a/libs/core/control.cpp +++ b/libs/core/control.cpp @@ -223,6 +223,23 @@ namespace control { release_fiber(); } + /** + * Gets the number of milliseconds elapsed since power on. + */ + //% help=control/millis weight=50 + //% blockId=control_running_time block="millis (ms)" + int millis() { + return system_timer_current_time(); + } + + /** + * Gets current time in microseconds. Overflows every ~18 minutes. + */ + //% + int micros() { + return system_timer_current_time_us() & 0x3fffffff; + } + /** * Schedules code that run in the background. */ @@ -232,6 +249,15 @@ namespace control { runInParallel(a); } + /** + * Blocks the calling thread until the specified event is raised. + */ + //% help=control/wait-for-event async + //% blockId=control_wait_for_event block="wait for event|from %src|with value %value" + void waitForEvent(int src, int value) { + pxt::waitForEvent(src, value); + } + /** * Resets the BBC micro:bit. */ diff --git a/libs/core/enums.d.ts b/libs/core/enums.d.ts index 29693dd7..34620484 100644 --- a/libs/core/enums.d.ts +++ b/libs/core/enums.d.ts @@ -111,13 +111,13 @@ declare namespace basic { //% jres=gestures.tiltbackwards LogoDown = 2, // MICROBIT_ACCELEROMETER_EVT_TILT_DOWN /** - * Raised when the screen is pointing down and the board is horizontal + * Raised when the screen is pointing up and the board is horizontal */ //% block="screen up" //% jres=gestures.frontsideup ScreenUp = 5, // MICROBIT_ACCELEROMETER_EVT_FACE_UP /** - * Raised when the screen is pointing up and the board is horizontal + * Raised when the screen is pointing down and the board is horizontal */ //% block="screen down" //% jres=gestures.backsideup diff --git a/libs/core/input.cpp b/libs/core/input.cpp index 03dc9592..d268df2a 100644 --- a/libs/core/input.cpp +++ b/libs/core/input.cpp @@ -75,13 +75,13 @@ enum class Gesture { //% jres=gestures.tiltbackwards LogoDown = MICROBIT_ACCELEROMETER_EVT_TILT_DOWN, /** - * Raised when the screen is pointing down and the board is horizontal + * Raised when the screen is pointing up and the board is horizontal */ //% block="screen up" //% jres=gestures.frontsideup ScreenUp = MICROBIT_ACCELEROMETER_EVT_FACE_UP, /** - * Raised when the screen is pointing up and the board is horizontal + * Raised when the screen is pointing down and the board is horizontal */ //% block="screen down" //% jres=gestures.backsideup @@ -363,26 +363,6 @@ namespace input { return 0; } - /** - * Gets the number of milliseconds elapsed since power on. - */ - //% help=input/running-time weight=50 blockGap=8 - //% blockId=device_get_running_time block="running time (ms)" - //% advanced=true - int runningTime() { - return system_timer_current_time(); - } - - /** - * Gets the number of microseconds elapsed since power on. - */ - //% help=input/running-time-micros weight=49 - //% blockId=device_get_running_time_micros block="running time (micros)" - //% advanced=true - int runningTimeMicros() { - return system_timer_current_time_us(); - } - /** * Obsolete, compass calibration is automatic. */ diff --git a/libs/core/input.ts b/libs/core/input.ts index 59377fa3..c6d0a487 100644 --- a/libs/core/input.ts +++ b/libs/core/input.ts @@ -55,4 +55,25 @@ namespace input { export function calibrate() { input.calibrateCompass(); } + + + /** + * Gets the number of milliseconds elapsed since power on. + */ + //% help=input/running-time weight=50 blockGap=8 + //% blockId=device_get_running_time block="running time (ms)" + //% advanced=true + export function runningTime() { + return control.millis(); + } + + /** + * Gets the number of microseconds elapsed since power on. + */ + //% help=input/running-time-micros weight=49 + //% blockId=device_get_running_time_micros block="running time (micros)" + //% advanced=true + export function runningTimeMicros() { + return control.micros(); + } } diff --git a/libs/core/music.ts b/libs/core/music.ts index 3c619a8a..70c30a8f 100644 --- a/libs/core/music.ts +++ b/libs/core/music.ts @@ -174,6 +174,8 @@ enum MusicEvent { */ //% color=#DF4600 weight=98 icon="\uf025" namespace music { + const INTERNAL_MELODY_ENDED = 5; + let beatsPerMinute: number = 120; //% whenUsed const freqs = hex` @@ -358,14 +360,69 @@ namespace music { currentBackgroundMelody = null; control.raiseEvent(MICROBIT_MELODY_ID, MusicEvent.MelodyEnded); control.raiseEvent(MICROBIT_MELODY_ID, MusicEvent.BackgroundMelodyResumed); + control.raiseEvent(MICROBIT_MELODY_ID, INTERNAL_MELODY_ENDED); } } control.raiseEvent(MICROBIT_MELODY_ID, currentMelody.background ? MusicEvent.BackgroundMelodyEnded : MusicEvent.MelodyEnded); + if (!currentMelody.background) + control.raiseEvent(MICROBIT_MELODY_ID, INTERNAL_MELODY_ENDED); currentMelody = null; }) } } + + /** + * Play a melody from the melody editor. + * @param melody - string of up to eight notes [C D E F G A B C5] or rests [-] separated by spaces, which will be played one at a time, ex: "E D G F B A C5 B " + * @param tempo - number in beats per minute (bpm), dictating how long each note will play for + */ + //% block="play melody $melody at tempo $tempo|(bpm)" blockId=playMelody + //% weight=85 blockGap=8 help=music/play-melody + //% melody.shadow="melody_editor" + //% tempo.min=40 tempo.max=500 + //% tempo.defl=120 + //% parts=headphone + export function playMelody(melody: string, tempo: number) { + melody = melody || ""; + setTempo(tempo); + let notes: string[] = melody.split(" ").filter(n => !!n); + let newOctave = false; + + // build melody string, replace '-' with 'R' and add tempo + // creates format like "C5-174 B4 A G F E D C " + for (let i = 0; i < notes.length; i++) { + if (notes[i] === "-") { + notes[i] = "R"; + } else if (notes[i] === "C5") { + newOctave = true; + } else if (newOctave) { // change the octave if necesary + notes[i] += "4"; + newOctave = false; + } + } + + music.beginMelody(notes, MelodyOptions.Once) + control.waitForEvent(MICROBIT_MELODY_ID, INTERNAL_MELODY_ENDED); + } + + /** + * Create a melody with the melody editor. + * @param melody + */ + //% block="$melody" blockId=melody_editor + //% blockHidden = true + //% weight=85 blockGap=8 + //% duplicateShadowOnDrag + //% melody.fieldEditor="melody" + //% melody.fieldOptions.decompileLiterals=true + //% melody.fieldOptions.decompileIndirectFixedInstances="true" + //% melody.fieldOptions.onParentBlock="true" + //% shim=TD_ID + export function melodyEditor(melody: string): string { + return melody; + } + /** * Stops the melodies * @param options which melody to stop diff --git a/libs/core/shims.d.ts b/libs/core/shims.d.ts index eb554327..9d21058b 100644 --- a/libs/core/shims.d.ts +++ b/libs/core/shims.d.ts @@ -346,22 +346,6 @@ declare namespace input { //% advanced=true shim=input::magneticForce function magneticForce(dimension: Dimension): int32; - /** - * Gets the number of milliseconds elapsed since power on. - */ - //% help=input/running-time weight=50 blockGap=8 - //% blockId=device_get_running_time block="running time (ms)" - //% advanced=true shim=input::runningTime - function runningTime(): int32; - - /** - * Gets the number of microseconds elapsed since power on. - */ - //% help=input/running-time-micros weight=49 - //% blockId=device_get_running_time_micros block="running time (micros)" - //% advanced=true shim=input::runningTimeMicros - function runningTimeMicros(): int32; - /** * Obsolete, compass calibration is automatic. */ @@ -388,6 +372,19 @@ declare namespace input { //% advanced=true declare namespace control { + /** + * Gets the number of milliseconds elapsed since power on. + */ + //% help=control/millis weight=50 + //% blockId=control_running_time block="millis (ms)" shim=control::millis + function millis(): int32; + + /** + * Gets current time in microseconds. Overflows every ~18 minutes. + */ + //% shim=control::micros + function micros(): int32; + /** * Schedules code that run in the background. */ @@ -395,6 +392,13 @@ declare namespace control { //% blockId="control_in_background" block="run in background" blockGap=8 shim=control::inBackground function inBackground(a: () => void): void; + /** + * Blocks the calling thread until the specified event is raised. + */ + //% help=control/wait-for-event async + //% blockId=control_wait_for_event block="wait for event|from %src|with value %value" shim=control::waitForEvent + function waitForEvent(src: int32, value: int32): void; + /** * Resets the BBC micro:bit. */ diff --git a/libs/radio-broadcast/pxt.json b/libs/radio-broadcast/pxt.json index b24a64b3..82f9ad60 100644 --- a/libs/radio-broadcast/pxt.json +++ b/libs/radio-broadcast/pxt.json @@ -1,12 +1,3 @@ { - "name": "radio-broadcast", - "description": "Adds new blocks for message communication in the radio category", - "files": [ - "pxt.json", - "radio-broadcast.ts" - ], - "dependencies": { - "core": "file:../core", - "radio": "file:../radio" - } + "additionalFilePath": "../../node_modules/pxt-common-packages/libs/radio-broadcast" } diff --git a/libs/radio-broadcast/radio-broadcast.ts b/libs/radio-broadcast/radio-broadcast.ts deleted file mode 100644 index c8b71835..00000000 --- a/libs/radio-broadcast/radio-broadcast.ts +++ /dev/null @@ -1,39 +0,0 @@ -namespace radio { - /** - * Gets the message code - */ - //% blockHidden=1 shim=ENUM_GET - //% blockId=radioMessageCode block="$msg" enumInitialMembers="message1" - //% enumName=RadioMessage enumMemberName=msg enumPromptHint="e.g. Start, Stop, Jump..." - //% enumIsHash=1 - export function __message(msg: number): number { - return msg; - } - - /** - * Broadcasts a message over radio - * @param msg - */ - //% blockId=radioBroadcastMessage block="radio send $msg" - //% msg.shadow=radioMessageCode draggableParameters - //% weight=200 - //% blockGap=8 - //% help=radio/send-message - export function sendMessage(msg: number): void { - // 0 is MICROBIT_EVT_ANY, shifting by 1 - radio.raiseEvent(DAL.MES_BROADCAST_GENERAL_ID, msg + 1); - } - - /** - * Registers code to run for a particular message - * @param msg - * @param handler - */ - //% blockId=radioOnMessageReceived block="on radio $msg received" - //% msg.shadow=radioMessageCode draggableParameters - //% weight=199 - //% help=radio/on-received-message - export function onReceivedMessage(msg: number, handler: () => void) { - control.onEvent(DAL.MES_BROADCAST_GENERAL_ID, msg + 1, handler); - } -} \ No newline at end of file diff --git a/libs/radio/README.md b/libs/radio/README.md deleted file mode 100644 index 1ffdf2b7..00000000 --- a/libs/radio/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# radio - -The radio library. - diff --git a/libs/radio/_locales/radio-jsdoc-strings.json b/libs/radio/_locales/radio-jsdoc-strings.json index b4f635f1..a8018f54 100644 --- a/libs/radio/_locales/radio-jsdoc-strings.json +++ b/libs/radio/_locales/radio-jsdoc-strings.json @@ -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.", diff --git a/libs/radio/pxt.json b/libs/radio/pxt.json index 9a1374cc..3eb5331a 100644 --- a/libs/radio/pxt.json +++ b/libs/radio/pxt.json @@ -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" + } } \ No newline at end of file diff --git a/libs/radio/radio.cpp b/libs/radio/radio.cpp deleted file mode 100644 index b4b324de..00000000 --- a/libs/radio/radio.cpp +++ /dev/null @@ -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); - } -} diff --git a/libs/radio/radio.ts b/libs/radio/radio.ts deleted file mode 100644 index 2f564e8c..00000000 --- a/libs/radio/radio.ts +++ /dev/null @@ -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; - } - } -} \ No newline at end of file diff --git a/libs/radio/shims.d.ts b/libs/radio/shims.d.ts index e7983bad..e7f3d06f 100644 --- a/libs/radio/shims.d.ts +++ b/libs/radio/shims.d.ts @@ -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; /** diff --git a/libs/radio/deprecated.ts b/libs/radio/targetoverrides.ts similarity index 79% rename from libs/radio/deprecated.ts rename to libs/radio/targetoverrides.ts index 3677a650..1dab5c14 100644 --- a/libs/radio/deprecated.ts +++ b/libs/radio/targetoverrides.ts @@ -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"); + } } \ No newline at end of file diff --git a/libs/radio/test.ts b/libs/radio/test.ts deleted file mode 100644 index 78182f64..00000000 --- a/libs/radio/test.ts +++ /dev/null @@ -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); -} diff --git a/package-lock.json b/package-lock.json index b7fca913..35a29d04 100644 --- a/package-lock.json +++ b/package-lock.json @@ -215,6 +215,13 @@ "bn.js": "^4.0.0", "inherits": "^2.0.1", "minimalistic-assert": "^1.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" + } } }, "assert": { @@ -368,9 +375,9 @@ "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" }, "bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.1.tgz", + "integrity": "sha512-IUTD/REb78Z2eodka1QZyyEk66pciRcP6Sroka0aI3tG/iwIdYLrBD62RsubR7vqdt3WyX8p4jxeatzmRSphtA==" }, "body-parser": { "version": "1.19.0", @@ -554,20 +561,40 @@ "requires": { "bn.js": "^4.1.0", "randombytes": "^2.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" + } } }, "browserify-sign": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", - "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.1.0.tgz", + "integrity": "sha512-VYxo7cDCeYUoBZ0ZCy4UyEUCP3smyBd4DRQM5nrFS1jJjPJjX7rP3oLRpPoWfkhQfyJ0I9ZbHbKafrFD/SGlrg==", "requires": { - "bn.js": "^4.1.1", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.2", - "elliptic": "^6.0.0", - "inherits": "^2.0.1", - "parse-asn1": "^5.0.0" + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.2", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } } }, "browserify-zlib": { @@ -579,12 +606,12 @@ } }, "browserslist": { - "version": "4.11.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.11.1.tgz", - "integrity": "sha512-DCTr3kDrKEYNw6Jb9HFxVLQNaue8z+0ZfRBRjmCunKDEXEBajKDj2Y+Uelg+Pi29OnvaSGwjOsnRyNEkXzHg5g==", + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.12.0.tgz", + "integrity": "sha512-UH2GkcEDSI0k/lRkuDSzFl9ZZ87skSy9w2XAn1MsZnL+4c4rqbBd3e82UWHbYDpztABrPBhZsTEeuxVfHppqDg==", "requires": { - "caniuse-lite": "^1.0.30001038", - "electron-to-chromium": "^1.3.390", + "caniuse-lite": "^1.0.30001043", + "electron-to-chromium": "^1.3.413", "node-releases": "^1.1.53", "pkg-up": "^2.0.0" } @@ -692,9 +719,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001043", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001043.tgz", - "integrity": "sha512-MrBDRPJPDBYwACtSQvxg9+fkna5jPXhJlKmuxenl/ml9uf8LHKlDmLpElu+zTW/bEz7lC1m0wTDD7jiIB+hgFg==" + "version": "1.0.30001051", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001051.tgz", + "integrity": "sha512-sw8UUnTlRevawTMZKN7vpfwSjCBVoiMPlYd8oT2VwNylyPCBdMAUmLGUApnYYTtIm5JXsQegUAY7GPHqgfDzjw==" }, "caseless": { "version": "0.12.0", @@ -732,9 +759,9 @@ } }, "chokidar": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.1.tgz", - "integrity": "sha512-4QYCEWOcK3OJrxwvyyAOxFuhpvOVCYkr33LPfFNBjAD/w3sEzWsp2BUOkI4l9bHvWioAd0rc6NlHUOEaWkTeqg==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.0.tgz", + "integrity": "sha512-aXAaho2VJtisB/1fg1+3nlLJqGOuewTzQpd/Tz0yTg2R0e4IGtshYvtjowyEumcBv2z+y4+kc75Mz7j5xJskcQ==", "requires": { "anymatch": "~3.1.1", "braces": "~3.0.2", @@ -743,7 +770,7 @@ "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", - "readdirp": "~3.3.0" + "readdirp": "~3.4.0" } }, "chownr": { @@ -936,6 +963,13 @@ "requires": { "bn.js": "^4.1.0", "elliptic": "^6.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" + } } }, "create-hash": { @@ -1005,9 +1039,9 @@ }, "dependencies": { "postcss": { - "version": "7.0.27", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", - "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", + "version": "7.0.29", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.29.tgz", + "integrity": "sha512-ba0ApvR3LxGvRMMiUa9n0WR4HjzcYm7tS+ht4/2Nd0NLtHpPIH77fuB9Xh1/yJVz9O/E/95Y/dn8ygWsyffXtw==", "requires": { "chalk": "^2.4.2", "source-map": "^0.6.1", @@ -1075,9 +1109,9 @@ }, "dependencies": { "postcss": { - "version": "7.0.27", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", - "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", + "version": "7.0.29", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.29.tgz", + "integrity": "sha512-ba0ApvR3LxGvRMMiUa9n0WR4HjzcYm7tS+ht4/2Nd0NLtHpPIH77fuB9Xh1/yJVz9O/E/95Y/dn8ygWsyffXtw==", "requires": { "chalk": "^2.4.2", "source-map": "^0.6.1", @@ -1129,9 +1163,9 @@ }, "dependencies": { "postcss": { - "version": "7.0.27", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", - "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", + "version": "7.0.29", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.29.tgz", + "integrity": "sha512-ba0ApvR3LxGvRMMiUa9n0WR4HjzcYm7tS+ht4/2Nd0NLtHpPIH77fuB9Xh1/yJVz9O/E/95Y/dn8ygWsyffXtw==", "requires": { "chalk": "^2.4.2", "source-map": "^0.6.1", @@ -1164,9 +1198,9 @@ }, "dependencies": { "postcss": { - "version": "7.0.27", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", - "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", + "version": "7.0.29", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.29.tgz", + "integrity": "sha512-ba0ApvR3LxGvRMMiUa9n0WR4HjzcYm7tS+ht4/2Nd0NLtHpPIH77fuB9Xh1/yJVz9O/E/95Y/dn8ygWsyffXtw==", "requires": { "chalk": "^2.4.2", "source-map": "^0.6.1", @@ -1361,6 +1395,13 @@ "bn.js": "^4.1.0", "miller-rabin": "^4.0.0", "randombytes": "^2.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" + } } }, "dom-serialize": { @@ -1460,9 +1501,9 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, "electron-to-chromium": { - "version": "1.3.413", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.413.tgz", - "integrity": "sha512-Jm1Rrd3siqYHO3jftZwDljL2LYQafj3Kki5r+udqE58d0i91SkjItVJ5RwlJn9yko8i7MOcoidVKjQlgSdd1hg==" + "version": "1.3.428", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.428.tgz", + "integrity": "sha512-u3+5jEfgLKq/hGO96YfAoOAM1tgFnRDTCD5mLuev44tttcXix+INtVegAkmGzUcfDsnzkPt51XXurXZLLwXt0w==" }, "elliptic": { "version": "6.5.2", @@ -1476,6 +1517,13 @@ "inherits": "^2.0.1", "minimalistic-assert": "^1.0.0", "minimalistic-crypto-utils": "^1.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" + } } }, "encodeurl": { @@ -1831,9 +1879,9 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fsevents": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz", - "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", "optional": true }, "function-bind": { @@ -1993,12 +2041,30 @@ "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" }, "hash-base": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", - "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" + } } }, "hash.js": { @@ -2761,12 +2827,19 @@ "requires": { "bn.js": "^4.0.0", "brorand": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" + } } }, "mime": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", - "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==" + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.5.tgz", + "integrity": "sha512-3hQhEUF027BuxZjQA3s7rIv/7VCQPa27hN9u9g87sEkWaKwQPuXOkVKtOeiyUrnWqTDiOs8Ed2rwg733mB0R5w==" }, "mime-db": { "version": "1.42.0", @@ -2825,9 +2898,9 @@ } }, "mkdirp-classic": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.2.tgz", - "integrity": "sha512-ejdnDQcR75gwknmMw/tx02AuRs8jCtqFoFqDZMjiNxsu85sRIJVXDKHuLYvUUPRBUtV2FpSZa9bL1BUa3BdR2g==" + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" }, "mocha": { "version": "5.1.0", @@ -2926,17 +2999,17 @@ "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" }, "node-abi": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.15.0.tgz", - "integrity": "sha512-FeLpTS0F39U7hHZU1srAK4Vx+5AHNVOTP+hxBNQknR/54laTHSFIJkDWDqiquY1LeLUgTfPN7sLPhMubx0PLAg==", + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.16.0.tgz", + "integrity": "sha512-+sa0XNlWDA6T+bDLmkCUYn6W5k5W6BPRL6mqzSCs6H/xUgtl4D5x2fORKDzopKiU6wsyn/+wXlRXwXeSp+mtoA==", "requires": { "semver": "^5.4.1" } }, "node-releases": { - "version": "1.1.53", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.53.tgz", - "integrity": "sha512-wp8zyQVwef2hpZ/dJH7SfSrIPD6YoJz6BDQDpGEkcA0s3LpAQoxBIYmfIq6QAhC1DhwsyCgTaTTcONwX8qzCuQ==" + "version": "1.1.55", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.55.tgz", + "integrity": "sha512-H3R3YR/8TjT5WPin/wOoHOUPHgvj8leuU/Keta/rwelEQN9pA/S2Dx8/se4pZ2LBxSd0nAGzsNzhqwa77v7F1w==" }, "noop-logger": { "version": "0.1.1", @@ -3254,9 +3327,9 @@ }, "dependencies": { "postcss": { - "version": "7.0.27", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", - "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", + "version": "7.0.29", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.29.tgz", + "integrity": "sha512-ba0ApvR3LxGvRMMiUa9n0WR4HjzcYm7tS+ht4/2Nd0NLtHpPIH77fuB9Xh1/yJVz9O/E/95Y/dn8ygWsyffXtw==", "requires": { "chalk": "^2.4.2", "source-map": "^0.6.1", @@ -3283,9 +3356,9 @@ }, "dependencies": { "postcss": { - "version": "7.0.27", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", - "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", + "version": "7.0.29", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.29.tgz", + "integrity": "sha512-ba0ApvR3LxGvRMMiUa9n0WR4HjzcYm7tS+ht4/2Nd0NLtHpPIH77fuB9Xh1/yJVz9O/E/95Y/dn8ygWsyffXtw==", "requires": { "chalk": "^2.4.2", "source-map": "^0.6.1", @@ -3314,9 +3387,9 @@ }, "dependencies": { "postcss": { - "version": "7.0.27", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", - "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", + "version": "7.0.29", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.29.tgz", + "integrity": "sha512-ba0ApvR3LxGvRMMiUa9n0WR4HjzcYm7tS+ht4/2Nd0NLtHpPIH77fuB9Xh1/yJVz9O/E/95Y/dn8ygWsyffXtw==", "requires": { "chalk": "^2.4.2", "source-map": "^0.6.1", @@ -3344,9 +3417,9 @@ }, "dependencies": { "postcss": { - "version": "7.0.27", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", - "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", + "version": "7.0.29", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.29.tgz", + "integrity": "sha512-ba0ApvR3LxGvRMMiUa9n0WR4HjzcYm7tS+ht4/2Nd0NLtHpPIH77fuB9Xh1/yJVz9O/E/95Y/dn8ygWsyffXtw==", "requires": { "chalk": "^2.4.2", "source-map": "^0.6.1", @@ -3369,9 +3442,9 @@ }, "dependencies": { "postcss": { - "version": "7.0.27", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", - "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", + "version": "7.0.29", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.29.tgz", + "integrity": "sha512-ba0ApvR3LxGvRMMiUa9n0WR4HjzcYm7tS+ht4/2Nd0NLtHpPIH77fuB9Xh1/yJVz9O/E/95Y/dn8ygWsyffXtw==", "requires": { "chalk": "^2.4.2", "source-map": "^0.6.1", @@ -3394,9 +3467,9 @@ }, "dependencies": { "postcss": { - "version": "7.0.27", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", - "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", + "version": "7.0.29", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.29.tgz", + "integrity": "sha512-ba0ApvR3LxGvRMMiUa9n0WR4HjzcYm7tS+ht4/2Nd0NLtHpPIH77fuB9Xh1/yJVz9O/E/95Y/dn8ygWsyffXtw==", "requires": { "chalk": "^2.4.2", "source-map": "^0.6.1", @@ -3419,9 +3492,9 @@ }, "dependencies": { "postcss": { - "version": "7.0.27", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", - "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", + "version": "7.0.29", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.29.tgz", + "integrity": "sha512-ba0ApvR3LxGvRMMiUa9n0WR4HjzcYm7tS+ht4/2Nd0NLtHpPIH77fuB9Xh1/yJVz9O/E/95Y/dn8ygWsyffXtw==", "requires": { "chalk": "^2.4.2", "source-map": "^0.6.1", @@ -3447,9 +3520,9 @@ }, "dependencies": { "postcss": { - "version": "7.0.27", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", - "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", + "version": "7.0.29", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.29.tgz", + "integrity": "sha512-ba0ApvR3LxGvRMMiUa9n0WR4HjzcYm7tS+ht4/2Nd0NLtHpPIH77fuB9Xh1/yJVz9O/E/95Y/dn8ygWsyffXtw==", "requires": { "chalk": "^2.4.2", "source-map": "^0.6.1", @@ -3482,9 +3555,9 @@ }, "dependencies": { "postcss": { - "version": "7.0.27", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", - "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", + "version": "7.0.29", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.29.tgz", + "integrity": "sha512-ba0ApvR3LxGvRMMiUa9n0WR4HjzcYm7tS+ht4/2Nd0NLtHpPIH77fuB9Xh1/yJVz9O/E/95Y/dn8ygWsyffXtw==", "requires": { "chalk": "^2.4.2", "source-map": "^0.6.1", @@ -3518,9 +3591,9 @@ }, "dependencies": { "postcss": { - "version": "7.0.27", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", - "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", + "version": "7.0.29", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.29.tgz", + "integrity": "sha512-ba0ApvR3LxGvRMMiUa9n0WR4HjzcYm7tS+ht4/2Nd0NLtHpPIH77fuB9Xh1/yJVz9O/E/95Y/dn8ygWsyffXtw==", "requires": { "chalk": "^2.4.2", "source-map": "^0.6.1", @@ -3551,9 +3624,9 @@ }, "dependencies": { "postcss": { - "version": "7.0.27", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", - "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", + "version": "7.0.29", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.29.tgz", + "integrity": "sha512-ba0ApvR3LxGvRMMiUa9n0WR4HjzcYm7tS+ht4/2Nd0NLtHpPIH77fuB9Xh1/yJVz9O/E/95Y/dn8ygWsyffXtw==", "requires": { "chalk": "^2.4.2", "source-map": "^0.6.1", @@ -3586,9 +3659,9 @@ }, "dependencies": { "postcss": { - "version": "7.0.27", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", - "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", + "version": "7.0.29", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.29.tgz", + "integrity": "sha512-ba0ApvR3LxGvRMMiUa9n0WR4HjzcYm7tS+ht4/2Nd0NLtHpPIH77fuB9Xh1/yJVz9O/E/95Y/dn8ygWsyffXtw==", "requires": { "chalk": "^2.4.2", "source-map": "^0.6.1", @@ -3619,9 +3692,9 @@ }, "dependencies": { "postcss": { - "version": "7.0.27", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", - "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", + "version": "7.0.29", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.29.tgz", + "integrity": "sha512-ba0ApvR3LxGvRMMiUa9n0WR4HjzcYm7tS+ht4/2Nd0NLtHpPIH77fuB9Xh1/yJVz9O/E/95Y/dn8ygWsyffXtw==", "requires": { "chalk": "^2.4.2", "source-map": "^0.6.1", @@ -3654,9 +3727,9 @@ }, "dependencies": { "postcss": { - "version": "7.0.27", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", - "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", + "version": "7.0.29", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.29.tgz", + "integrity": "sha512-ba0ApvR3LxGvRMMiUa9n0WR4HjzcYm7tS+ht4/2Nd0NLtHpPIH77fuB9Xh1/yJVz9O/E/95Y/dn8ygWsyffXtw==", "requires": { "chalk": "^2.4.2", "source-map": "^0.6.1", @@ -3681,9 +3754,9 @@ }, "dependencies": { "postcss": { - "version": "7.0.27", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", - "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", + "version": "7.0.29", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.29.tgz", + "integrity": "sha512-ba0ApvR3LxGvRMMiUa9n0WR4HjzcYm7tS+ht4/2Nd0NLtHpPIH77fuB9Xh1/yJVz9O/E/95Y/dn8ygWsyffXtw==", "requires": { "chalk": "^2.4.2", "source-map": "^0.6.1", @@ -3714,9 +3787,9 @@ }, "dependencies": { "postcss": { - "version": "7.0.27", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", - "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", + "version": "7.0.29", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.29.tgz", + "integrity": "sha512-ba0ApvR3LxGvRMMiUa9n0WR4HjzcYm7tS+ht4/2Nd0NLtHpPIH77fuB9Xh1/yJVz9O/E/95Y/dn8ygWsyffXtw==", "requires": { "chalk": "^2.4.2", "source-map": "^0.6.1", @@ -3747,9 +3820,9 @@ }, "dependencies": { "postcss": { - "version": "7.0.27", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", - "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", + "version": "7.0.29", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.29.tgz", + "integrity": "sha512-ba0ApvR3LxGvRMMiUa9n0WR4HjzcYm7tS+ht4/2Nd0NLtHpPIH77fuB9Xh1/yJVz9O/E/95Y/dn8ygWsyffXtw==", "requires": { "chalk": "^2.4.2", "source-map": "^0.6.1", @@ -3779,9 +3852,9 @@ }, "dependencies": { "postcss": { - "version": "7.0.27", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", - "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", + "version": "7.0.29", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.29.tgz", + "integrity": "sha512-ba0ApvR3LxGvRMMiUa9n0WR4HjzcYm7tS+ht4/2Nd0NLtHpPIH77fuB9Xh1/yJVz9O/E/95Y/dn8ygWsyffXtw==", "requires": { "chalk": "^2.4.2", "source-map": "^0.6.1", @@ -3811,9 +3884,9 @@ }, "dependencies": { "postcss": { - "version": "7.0.27", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", - "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", + "version": "7.0.29", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.29.tgz", + "integrity": "sha512-ba0ApvR3LxGvRMMiUa9n0WR4HjzcYm7tS+ht4/2Nd0NLtHpPIH77fuB9Xh1/yJVz9O/E/95Y/dn8ygWsyffXtw==", "requires": { "chalk": "^2.4.2", "source-map": "^0.6.1", @@ -3843,9 +3916,9 @@ }, "dependencies": { "postcss": { - "version": "7.0.27", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", - "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", + "version": "7.0.29", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.29.tgz", + "integrity": "sha512-ba0ApvR3LxGvRMMiUa9n0WR4HjzcYm7tS+ht4/2Nd0NLtHpPIH77fuB9Xh1/yJVz9O/E/95Y/dn8ygWsyffXtw==", "requires": { "chalk": "^2.4.2", "source-map": "^0.6.1", @@ -3876,9 +3949,9 @@ }, "dependencies": { "postcss": { - "version": "7.0.27", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", - "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", + "version": "7.0.29", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.29.tgz", + "integrity": "sha512-ba0ApvR3LxGvRMMiUa9n0WR4HjzcYm7tS+ht4/2Nd0NLtHpPIH77fuB9Xh1/yJVz9O/E/95Y/dn8ygWsyffXtw==", "requires": { "chalk": "^2.4.2", "source-map": "^0.6.1", @@ -3907,9 +3980,9 @@ }, "dependencies": { "postcss": { - "version": "7.0.27", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", - "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", + "version": "7.0.29", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.29.tgz", + "integrity": "sha512-ba0ApvR3LxGvRMMiUa9n0WR4HjzcYm7tS+ht4/2Nd0NLtHpPIH77fuB9Xh1/yJVz9O/E/95Y/dn8ygWsyffXtw==", "requires": { "chalk": "^2.4.2", "source-map": "^0.6.1", @@ -3939,9 +4012,9 @@ }, "dependencies": { "postcss": { - "version": "7.0.27", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", - "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", + "version": "7.0.29", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.29.tgz", + "integrity": "sha512-ba0ApvR3LxGvRMMiUa9n0WR4HjzcYm7tS+ht4/2Nd0NLtHpPIH77fuB9Xh1/yJVz9O/E/95Y/dn8ygWsyffXtw==", "requires": { "chalk": "^2.4.2", "source-map": "^0.6.1", @@ -3972,9 +4045,9 @@ }, "dependencies": { "postcss": { - "version": "7.0.27", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", - "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", + "version": "7.0.29", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.29.tgz", + "integrity": "sha512-ba0ApvR3LxGvRMMiUa9n0WR4HjzcYm7tS+ht4/2Nd0NLtHpPIH77fuB9Xh1/yJVz9O/E/95Y/dn8ygWsyffXtw==", "requires": { "chalk": "^2.4.2", "source-map": "^0.6.1", @@ -4000,9 +4073,9 @@ }, "dependencies": { "postcss": { - "version": "7.0.27", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", - "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", + "version": "7.0.29", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.29.tgz", + "integrity": "sha512-ba0ApvR3LxGvRMMiUa9n0WR4HjzcYm7tS+ht4/2Nd0NLtHpPIH77fuB9Xh1/yJVz9O/E/95Y/dn8ygWsyffXtw==", "requires": { "chalk": "^2.4.2", "source-map": "^0.6.1", @@ -4043,9 +4116,9 @@ }, "dependencies": { "postcss": { - "version": "7.0.27", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", - "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", + "version": "7.0.29", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.29.tgz", + "integrity": "sha512-ba0ApvR3LxGvRMMiUa9n0WR4HjzcYm7tS+ht4/2Nd0NLtHpPIH77fuB9Xh1/yJVz9O/E/95Y/dn8ygWsyffXtw==", "requires": { "chalk": "^2.4.2", "source-map": "^0.6.1", @@ -4075,9 +4148,9 @@ }, "dependencies": { "postcss": { - "version": "7.0.27", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", - "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", + "version": "7.0.29", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.29.tgz", + "integrity": "sha512-ba0ApvR3LxGvRMMiUa9n0WR4HjzcYm7tS+ht4/2Nd0NLtHpPIH77fuB9Xh1/yJVz9O/E/95Y/dn8ygWsyffXtw==", "requires": { "chalk": "^2.4.2", "source-map": "^0.6.1", @@ -4092,9 +4165,9 @@ } }, "postcss-value-parser": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.0.3.tgz", - "integrity": "sha512-N7h4pG+Nnu5BEIzyeaaIYWs0LI5XC40OrRh5L60z0QjFsqGWcHcbkBvpe1WYpcIS9yQ8sOi/vIPt1ejQCrMVrg==" + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz", + "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==" }, "prebuild-install": { "version": "5.3.3", @@ -4185,6 +4258,13 @@ "parse-asn1": "^5.0.0", "randombytes": "^2.0.1", "safe-buffer": "^5.1.2" + }, + "dependencies": { + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" + } } }, "pump": { @@ -4250,18 +4330,18 @@ } }, "pxt-common-packages": { - "version": "6.21.9", - "resolved": "https://registry.npmjs.org/pxt-common-packages/-/pxt-common-packages-6.21.9.tgz", - "integrity": "sha512-vbUtA4GDE+N4YCaWdC9mBVr0B1xHMj5Ad4NtxFRxbpkeuceZDd0OvGfZvFYHn624t9jUcfuwl4dmhZrXUAPclg==", + "version": "6.21.10", + "resolved": "https://registry.npmjs.org/pxt-common-packages/-/pxt-common-packages-6.21.10.tgz", + "integrity": "sha512-GsNfjTe0YWQX4nn5lMiXST79yeb8OGCZbeJAP6I0dFfahoCM1H2tQqY/hMEPAznY1QZEgHkYvpw8SEWJvbK6Vw==", "requires": { "@jacdac/jacdac-ts": "^0.0.9", - "pxt-core": "^5.34.1" + "pxt-core": "^5.36.2" } }, "pxt-core": { - "version": "5.36.1", - "resolved": "https://registry.npmjs.org/pxt-core/-/pxt-core-5.36.1.tgz", - "integrity": "sha512-tls8in91gUL1IVG+iLnAsJqEwWsva645snPNvuzM/fzxmna6kA1ZwlHFDAPcpFukZ32cIORyRxRq8ZsplaKVTw==", + "version": "5.36.9", + "resolved": "https://registry.npmjs.org/pxt-core/-/pxt-core-5.36.9.tgz", + "integrity": "sha512-2rrKF+dSrYRwc0GjhPKNR4onzrN4njaWoXQrb9fBvOxsDvpRdrcNnzOi3X7aMv4ocoBYG6wEkCZnk+Ti+AOEFw==", "requires": { "applicationinsights-js": "^1.0.20", "bluebird": "3.5.1", @@ -4399,11 +4479,11 @@ } }, "readdirp": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.3.0.tgz", - "integrity": "sha512-zz0pAkSPOXXm1viEwygWIPSPkcBYjW1xU5j/JBh5t9bGCJwa6f9+BJa6VaB2g+b55yVrmXzqkyLf4xaWYM0IkQ==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", + "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", "requires": { - "picomatch": "^2.0.7" + "picomatch": "^2.2.1" } }, "request": { @@ -4504,9 +4584,9 @@ "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" }, "resolve": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.16.1.tgz", - "integrity": "sha512-rmAglCSqWWMrrBv/XM6sW0NuRFiKViw/W4d9EbC4pt+49H8JwHy+mcGmALTEg504AUDcLTvb1T2q3E9AnmY+ig==", + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", "requires": { "path-parse": "^1.0.6" } @@ -4588,9 +4668,9 @@ }, "dependencies": { "postcss": { - "version": "7.0.27", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", - "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", + "version": "7.0.29", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.29.tgz", + "integrity": "sha512-ba0ApvR3LxGvRMMiUa9n0WR4HjzcYm7tS+ht4/2Nd0NLtHpPIH77fuB9Xh1/yJVz9O/E/95Y/dn8ygWsyffXtw==", "requires": { "chalk": "^2.4.2", "source-map": "^0.6.1", @@ -5001,9 +5081,9 @@ }, "dependencies": { "postcss": { - "version": "7.0.27", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", - "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", + "version": "7.0.29", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.29.tgz", + "integrity": "sha512-ba0ApvR3LxGvRMMiUa9n0WR4HjzcYm7tS+ht4/2Nd0NLtHpPIH77fuB9Xh1/yJVz9O/E/95Y/dn8ygWsyffXtw==", "requires": { "chalk": "^2.4.2", "source-map": "^0.6.1", diff --git a/package.json b/package.json index 519b09f6..98b4be38 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "typescript": "^3.7.5" }, "dependencies": { - "pxt-common-packages": "6.21.9", - "pxt-core": "5.36.1" + "pxt-common-packages": "6.21.10", + "pxt-core": "5.36.9" } } diff --git a/pxtarget.json b/pxtarget.json index ca6c140e..05be91a8 100644 --- a/pxtarget.json +++ b/pxtarget.json @@ -302,14 +302,11 @@ "experiments": [ "allowPackageExtensions", "instructions", - "debugger", "debugExtensionCode", "bluetoothUartConsole", "bluetoothPartialFlashing", "simScreenshot", - "simGif", - "qrCode", - "githubBlocksDiff" + "simGif" ], "bluetoothUartFilters": [ { @@ -325,14 +322,6 @@ "name": "Reference", "path": "/reference" }, - { - "name": "Blocks", - "path": "/blocks" - }, - { - "name": "JavaScript", - "path": "/javascript" - }, { "name": "Hardware", "path": "/device" @@ -347,6 +336,12 @@ "coloredToolbox": true, "monacoToolbox": true, "hasAudio": true, + "socialOptions": { + "orgTwitterHandle": "MSMakeCode", + "hashtags": "MakeCode", + "discourse": "https://forum.makecode.com/", + "discourseCategory": "micro:bit" + }, "blocklyOptions": { "grid": { "spacing": 45, @@ -373,6 +368,7 @@ }, "highContrast": true, "greenScreen": true, + "accessibleBlocks": true, "print": true, "selectLanguage": true, "availableLocales": [ @@ -391,7 +387,7 @@ "ja", "ko", "nl", - "no", + "nb", "pl", "pt-BR", "pt-PT", @@ -416,6 +412,7 @@ }, "showProjectSettings": true, "scriptManager": true, + "debugger": true, "simGifTransparent": "rgba(0,0,0,0)", "simGifMaxFrames": 44, "simScreenshotMaxUriLength": 300000, diff --git a/sim/dalboard.ts b/sim/dalboard.ts index de2b9da4..6f18e9cd 100644 --- a/sim/dalboard.ts +++ b/sim/dalboard.ts @@ -1,7 +1,8 @@ /// namespace pxsim { - export class DalBoard extends CoreBoard { + export class DalBoard extends CoreBoard + implements RadioBoard { // state & update logic for component services ledMatrixState: LedMatrixState; edgeConnectorState: EdgeConnectorState; @@ -67,7 +68,10 @@ namespace pxsim { "P3": DAL.MICROBIT_ID_IO_P16 } }); - this.builtinParts["radio"] = this.radioState = new RadioState(runtime); + this.builtinParts["radio"] = this.radioState = new RadioState(runtime, { + ID_RADIO: DAL.MICROBIT_ID_RADIO, + RADIO_EVT_DATAGRAM: DAL.MICROBIT_RADIO_EVT_DATAGRAM + }); this.builtinParts["accelerometer"] = this.accelerometerState = new AccelerometerState(runtime); this.builtinParts["serial"] = this.serialState = new SerialState(); this.builtinParts["thermometer"] = this.thermometerState = new ThermometerState(); @@ -173,7 +177,7 @@ namespace pxsim { pxsim.initCurrentRuntime = initRuntimeWithDalBoard; } - export function board() { + export function board(): DalBoard { return runtime.board as DalBoard; } } diff --git a/sim/state/edgeconnectorsim.ts b/sim/state/edgeconnectorsim.ts index d4e04a45..b136fbd7 100644 --- a/sim/state/edgeconnectorsim.ts +++ b/sim/state/edgeconnectorsim.ts @@ -32,6 +32,11 @@ namespace pxsim { setPull(pull: number) { this.pull = pull; + switch(pull) { + case PinPullMode.PullDown: this.value = 0; break; + case PinPullMode.PullUp: this.value = 1023; break; + default: this.value = Math_.randomRange(0, 1023); break; + } } analogReadPin(): number { diff --git a/sim/state/misc.ts b/sim/state/misc.ts index c1e4a099..d672b190 100644 --- a/sim/state/misc.ts +++ b/sim/state/misc.ts @@ -47,6 +47,19 @@ namespace pxsim.control { export function waitMicros(micros: number) { // TODO } + export function waitForEvent(id: number, evid: number) { + const cb = getResume(); + board().bus.wait(id, evid, cb); + } + + export function millis(): number { + return runtime.runningTime(); + } + + export function micros(): number { + return runtime.runningTimeUs(); + } + export function deviceName(): string { let b = board(); @@ -94,14 +107,6 @@ namespace pxsim.pxtcore { } namespace pxsim.input { - export function runningTime(): number { - return runtime.runningTime(); - } - - export function runningTimeMicros(): number { - return runtime.runningTimeUs(); - } - export function calibrateCompass() { // device calibrates... } diff --git a/sim/state/radio.ts b/sim/state/radio.ts deleted file mode 100644 index 72edb713..00000000 --- a/sim/state/radio.ts +++ /dev/null @@ -1,147 +0,0 @@ -namespace pxsim { - export interface PacketBuffer { - payload: SimulatorRadioPacketPayload; - rssi: number; - serial: number; - time: number; - } - - // Extends interface in pxt-core - export interface SimulatorRadioPacketPayload { - bufferData?: Uint8Array; - } - - export class RadioDatagram { - datagram: PacketBuffer[] = []; - lastReceived: PacketBuffer = RadioDatagram.defaultPacket(); - - constructor(private runtime: Runtime) { - } - - queue(packet: PacketBuffer) { - if (this.datagram.length < 4) { - this.datagram.push(packet); - } - (runtime.board).bus.queue(DAL.MICROBIT_ID_RADIO, DAL.MICROBIT_RADIO_EVT_DATAGRAM); - } - - send(payload: SimulatorRadioPacketPayload) { - const b = board(); - Runtime.postMessage({ - type: "radiopacket", - broadcast: true, - rssi: -42, // -42 is the strongest signal - serial: b.radioState.transmitSerialNumber ? pxsim.control.deviceSerialNumber() : 0, - time: new Date().getTime(), - payload - }) - } - - recv(): PacketBuffer { - let r = this.datagram.shift(); - if (!r) r = RadioDatagram.defaultPacket(); - return this.lastReceived = r; - } - - private static defaultPacket(): PacketBuffer { - return { - rssi: -1, - serial: 0, - time: 0, - payload: { type: -1, groupId: 0, bufferData: new Uint8Array(0) } - }; - } - } - - export class RadioState { - power = 0; - transmitSerialNumber = false; - datagram: RadioDatagram; - groupId: number; - band: number; - - constructor(runtime: Runtime) { - this.datagram = new RadioDatagram(runtime); - this.power = 6; // default value - this.groupId = 0; - this.band = 7; // https://github.com/lancaster-university/microbit-dal/blob/master/inc/core/MicroBitConfig.h#L320 - } - - public setGroup(id: number) { - this.groupId = id & 0xff; // byte only - } - - setTransmitPower(power: number) { - power = power | 0; - this.power = Math.max(0, Math.min(7, power)); - } - - setTransmitSerialNumber(sn: boolean) { - this.transmitSerialNumber = !!sn; - } - - setFrequencyBand(band: number) { - band = band | 0; - if (band < 0 || band > 83) return; - this.band = band; - } - - raiseEvent(id: number, eventid: number) { - Runtime.postMessage({ - type: "eventbus", - broadcast: true, - id, - eventid, - power: this.power, - group: this.groupId - }) - } - - receivePacket(packet: SimulatorRadioPacketMessage) { - if (this.groupId == packet.payload.groupId) - this.datagram.queue(packet) - } - } -} - -namespace pxsim.radio { - export function raiseEvent(id: number, eventid: number): void { - board().radioState.raiseEvent(id, eventid); - } - - export function setGroup(id: number): void { - board().radioState.setGroup(id); - } - - export function setTransmitPower(power: number): void { - board().radioState.setTransmitPower(power); - } - - export function setFrequencyBand(band: number) { - board().radioState.setFrequencyBand(band); - } - - export function sendRawPacket(buf: RefBuffer) { - let cb = getResume(); - board().radioState.datagram.send({ - type: 0, - groupId: board().radioState.groupId, - bufferData: buf.data - }); - setTimeout(cb, 1); - } - - export function readRawPacket() { - const packet = board().radioState.datagram.recv(); - return new RefBuffer(packet.payload.bufferData) - } - - export function receivedSignalStrength(): number { - return board().radioState.datagram.lastReceived.rssi; - } - - export function onDataReceived(handler: RefAction): void { - pxtcore.registerWithDal(DAL.MICROBIT_ID_RADIO, DAL.MICROBIT_RADIO_EVT_DATAGRAM, handler); - readRawPacket(); - } -} \ No newline at end of file diff --git a/sim/tsconfig.json b/sim/tsconfig.json index d043b21a..2fa70fa6 100644 --- a/sim/tsconfig.json +++ b/sim/tsconfig.json @@ -11,5 +11,11 @@ "lib": ["dom", "dom.iterable", "scripthost", "es6"], "types": ["bluebird"], "typeRoots": ["../node_modules/@types"] - } + }, + "include": [ + "*.ts", + "state/*.ts", + "visuals/*.ts", + "../node_modules/pxt-common-packages/libs/radio/sim/*.ts" + ] } diff --git a/sim/visuals/microbit.ts b/sim/visuals/microbit.ts index c1c4bd14..f7e1fa7b 100644 --- a/sim/visuals/microbit.ts +++ b/sim/visuals/microbit.ts @@ -1106,10 +1106,10 @@ namespace pxsim.visuals { } else if (pin.mode & PinFlags.Touch) { v = pin.touched ? "0%" : "100%"; - if (text) text.textContent = ""; + if (text) text.textContent = "TOUCHED"; } else { v = "100%"; - if (text) text.textContent = ""; + if (text) text.textContent = "unused"; } if (v) svg.setGradientValue(this.pinGradients[index], v); } @@ -1558,4 +1558,4 @@ namespace pxsim.visuals { }) } } -} \ No newline at end of file +} diff --git a/targetconfig.json b/targetconfig.json index b5c30d3e..4b55f7ed 100644 --- a/targetconfig.json +++ b/targetconfig.json @@ -185,7 +185,18 @@ "EBOTICS/pxt-eboticsMIBO", "KitronikLtd/pxt-kitronik-halohd", "dugbraden/pxt-climate-action-kit", - "alsrobot-microbit-makecode-packages/MiniCruise" + "alsrobot-microbit-makecode-packages/MiniCruise", + "4tronix/ServoBit", + "DFRobot/pxt-maqueen", + "DFRobot/pxt-DFRobot-microIoT", + "mu-opensource/pxt-muvision", + "KitronikLtd/pxt-kitronik-clip-detector", + "DFRobot/pxt-DFRobot-NaturalScience", + "strawbees/pxt-robotic-inventions", + "daferdur/pxt-myHX711", + "CytronTechnologies/pxt-edubit", + "MakeAndLearn/pxt-microshield", + "elecfreaks/pxt-TPBot" ], "preferredRepos": [ "Microsoft/pxt-neopixel", @@ -199,33 +210,6 @@ "MKleinSB/pxt-foldio" ] }, - "languages": [ - "en", - "ar", - "cs", - "da", - "de", - "el", - "es-ES", - "fi", - "fr", - "hu", - "it", - "ja", - "ko", - "nl", - "no", - "pt-BR", - "pt-PT", - "ru", - "si-LK", - "sk", - "sv-SE", - "tr", - "uk", - "zh-CN", - "zh-TW" - ], "galleries": { "First Steps": "calliope/firststeps", "Tutorials": "calliope/tutorials", diff --git a/theme/site/elements/button.overrides b/theme/site/elements/button.overrides index cba59efe..c172e5f5 100644 --- a/theme/site/elements/button.overrides +++ b/theme/site/elements/button.overrides @@ -1,3 +1,3 @@ /******************************* Site Overrides -*******************************/ +*******************************/ \ No newline at end of file diff --git a/theme/site/globals/site.variables b/theme/site/globals/site.variables old mode 100644 new mode 100755