Skip to content
Visor Developers

Neural Band

Scope: band, and motion for the band's motion. The Meta Ray-Ban Display with a paired Meta Neural Band. Without a band, band.status says paired: false, and the gestures, the motion and the buzz fail with unsupported.

The band works with apps in one of two ways, which the person picks in Visor. Your code is the same for both.

  • With the Display, the usual way. The band talks to the Display, which uses its gestures to move around. Visor reads them through a session with the Display, so the Display acts on each gesture as usual and the app gets it too. A buzz borrows the band from the Display for a moment.
  • Shared with the phone. The band stays connected to the phone, and the Display reaches it through the phone, as Meta's relay lease does. Gestures come straight from the band, a buzz goes out at once, and the band's motion sensors are open to apps. The person turns it on in Visor > Settings > Neural Band > Share with the phone. When sharing does not work, Visor turns it off itself: the band goes back to the Display, and Visor's band settings say why.

A band the person paired to the Display with Meta's app shows in band.status with the battery the Display reports, and held: false. Its gestures reach apps all the same. The buzz and sharing need Visor to hold the band's keys, which it does once the person sets the band up in Visor's band settings; until then the buzz fails with unsupported and the reason not_set_up.

Gestures

visor.band.gestures.collect { gesture ->
    when {
        gesture.finger == Finger.INDEX && gesture.derived == GestureAction.DOUBLE_TAP -> next()
        gesture.finger == Finger.MIDDLE && gesture.derived == GestureAction.HOLD -> back()
    }
}

With the band on the Display, collecting gestures opens a session with the Display, which shows nothing on its screen. The first time, Visor asks the person once to set the glasses up for apps. The session needs the glasses worn, and the Display ends it when another app comes to the front; Visor opens it again while your app collects. Collect only while your app needs the gestures, for example while one screen is in front. With the band shared, the gestures come straight from it and no session is needed.

A Gesture:

Field Type Meaning
finger Finger thumb, index or middle.
action GestureAction What the finger did. With the band on the Display: tap, double_tap, triple_tap, hold, or a thumb swipe up, down, left, right. With the band shared, the band's own events: press, release, tap, double_tap, click, or a swipe.
derived GestureAction? What the band made of the events: tap, double_tap, hold, release, or a swipe. With the band on the Display it is the same as action.
time Long When the phone got it, in milliseconds since 1970.

Act on derived and your app works either way. The Display tells taps apart before it forwards them: a double tap comes as one double_tap, after its first tap. A middle-finger tap is the Display's back, so the Display goes back while your app gets the tap. Sets like GestureAction grow over time; treat values you do not know as nothing to act on.

Status

visor.band.status.collect { status -> }

A BandStatus:

Field Type Meaning
paired Boolean False when no band is paired with the glasses.
link Link The phone's own link to the band: up while the phone borrows it for a buzz, and all along while the band is shared.
battery Int? 0 to 100.
charging Boolean?
leftHanded Boolean? True when the band is set for the left wrist.
borrowed Boolean True while the band sends its gestures to the phone's own link: during a lesson in Visor, or while an app reads the gestures of a shared band.
held Boolean? True when Visor holds the band's keys, so the phone can buzz and share it. False for a band only the Display holds.
shared Boolean True while the person shares the band with the phone.

Motion

Scope: motion. A band shared with the phone.

if (visor.band.status.first().shared) {
    visor.band.motion.collect { sample -> }                // 30 samples a second
    visor.band.motion(rateHz = 60).collect { sample -> }
}

The band's own sensors on the wrist, in the same MotionSample as the glasses' motion, with source band: accelerometer in m/s², gyroscope in rad/s, magnetometer as the band reports it, and the band's own fused orientation. The band sends each sensor on its own, so a sample carries the newest reading of each. time is when the phone got it, in nanoseconds; only the differences between samples mean something. Use it to point with the wrist, to know when the wearer raises the arm, or to count repetitions.

Without sharing, or when sharing stops while you read, the stream ends with unsupported and the reason not_shared. Its message names the setting, so you can show it to the person. Reading the band's sensors without sharing would take the band from the Display.

In a test, set fake.band.shared = true, wait for fake.band.motionRate, then send readings with fake.band.motion(ax, ay, az) or a whole MotionSample.

Vibration

visor.band.buzz()                             // 400 ms at full strength: the wearer notices it
visor.band.buzz(80.milliseconds, 0.5f)        // 10 ms to 1 s, strength above 0 up to 1

With the band on the Display, a buzz borrows the band for a moment and gives it back; with the band shared, it goes out at once. It fails with not_connected when the band's link does not come up in time, and with refused when the band turns it down.

JSON-RPC

Name Params Answer
Method band.status none a BandStatus
Method band.buzz durationMs (10 to 1000, default 400), strength (1 to 255, default 255) {}
Topic band.status none BandStatus now, then on each change
Topic band.gestures none Gesture
Topic band.motion rateHz (5 to 60, default 30) a MotionSample with source band

Without a band, visor simulate band.gestures makes Visor send only the gestures you type. See Testing.

On the wire: Neural Band.