В моем предыдущем блоге я показал вам, как разместить модуль wasm в программе на Rust, используя wasmi. Вы можете проверить этот блог для справки. В этом блоге я буду использовать wasmi для создания программы на ржавчине, которая будет действовать как хост wasm на Raspberry Pi. Мы скомпилируем программу rust в armv7, поскольку устройства Raspberry Pi 2+ являются устройствами arm v7. Затем мы разместим модуль WebAssembly на Raspberry Pi.

Прежде всего, мы напишем программу на Rust, которую будем размещать, а затем скомпилируем ее в wasm. Мы собираемся создать индикатор заряда батареи. Его работа довольно проста. Один из входных сигналов датчика отображает количество
оставшегося заряда батареи в процентах. В соответствии с этим процентом мы будем управлять цветом группы из восьми светодиодов. Давайте начнем.

Индикатор батареи

Светодиоды могут загораться цветами в виде комбинации компонентов RGB в диапазоне от 0 до 255. Фактическое аппаратное обеспечение, которое используется Blinkt! Пиморони. Вы можете купить это онлайн, если хотите реализовать это.

На Blinkt! есть 8 светодиодов. Таким образом, основная логика состоит в том, чтобы разделить максимальный процент заряда батареи на 8, т. е. 100 на 8 (100/8 = 12,5), чтобы получить процент на каждый светодиод. Мы можем назвать это значение процент_на_пиксель. Затем мы можем использовать это значение для включения светодиодов на основе числа, которое мы получаем после деления текущего процента заряда батареи на процент_на_пиксель. Если значение после деления представляет собой число с плавающей запятой, мы берем максимальное значение.

Например, если процент заряда батареи равен 80, то количество загорающихся светодиодов будет равно 7, так как 80 / 12,5 = 6,4, поэтому мы берем максимальное значение.

Итак, давайте посмотрим на код, а затем обсудим его дальше.

#[derive(PartialEq, Debug, Clone)]
struct LedColor(i32, i32, i32); 

const SENSOR_BATTERY: i32 = 20;

const OFF:LedColor =  LedColor(0, 0, 0);
const YELLOW: LedColor = LedColor(255, 255, 0);
const GREEN: LedColor = LedColor(0, 255, 0);
const RED: LedColor = LedColor(255, 0, 0);
const PCT_PER_PIXEL: f64 = 12.5_f64;


extern "C" {
    fn set_led(led_index: i32, r: i32, g: i32, b: i32); 
}


#[no_mangle]
pub extern "C" fn sensor_update(sensor_id: i32, sensor_value: f64) -> f64 { 
    if sensor_id == SENSOR_BATTERY {
        set_leds(get_led_values(sensor_value));
    }
    sensor_value
}

#[no_mangle]
pub extern "C" fn apply(_frame: u32) {
    // NO OP, not an animated indicator
}


fn get_led_values(battery_remaining: f64) -> [LedColor; 8] {
    let mut arr: [LedColor; 8] = [OFF,OFF,OFF,OFF,OFF,OFF,OFF,OFF,];
    let lit = (battery_remaining / PCT_PER_PIXEL).ceil();

    // 0 - 20 : Red
    // 21 - 50 : Yellow
    // 51 - 100 : Green

    let color = if 0.0 <= battery_remaining &&
        battery_remaining <= 20.0 {
        RED
    } else if battery_remaining > 20.0 && battery_remaining < 50.0 {
        YELLOW
    } else {
        GREEN
    };

    for index in 0..lit as usize {
        arr[index] = color.clone();
    }
    arr
}

fn set_leds(values: [LedColor; 8]) { // (5)
    for index in 0..8 {
        let LedColor(r, g, b) = values[index];
        unsafe {
            set_led(index as i32, r,g,b);
        }
    }
}

Программа определяет кортеж structLedColor для значения RGB каждого светодиода. SENSOR_BATTERY – это идентификатор датчика, определяющий уровень заряда батареи в процентах. Затем мы определяем значение RGB для каждого цвета, который будем использовать для представления процента заряда батареи.

Эта программа экспортирует две функции: sensor_update и apply, а также импортирует функцию set_led с хоста. Давайте посмотрим, что делают эти функции.

функция sensor_update

Функция sensor_update принимает два значения: sensor_id и sensor_value. sensor_id – это идентификатор датчика, отправляющего процент заряда батареи, а sensor_value – фактический процент заряда батареи.

Функция проверяет, поступает ли вход от датчика батареи или нет. Затем он вызывает функцию set_leds, которая устанавливает светодиоды на Blinkt! как ON или OFF, а также устанавливает цвет светодиодов. Функция apply() не определена, поскольку она используется для создания анимации.

функция set_leds

Функция set_leds принимает в качестве аргументов массив объектов LedColor. LedColor — это кортежная структура, определяющая значения RGB для цветов светодиодов. Он устанавливает желаемые светодиоды с соответствующими цветами на хосте. Он делает небезопасный вызов импортированной функции set_let для установки светодиодов. Небезопасный означает, что Rust не гарантирует безопасность типов этой функции, так как это импортированная функция.

функция get_led_values

Эта функция принимает процент заряда батареи в качестве аргумента, который передается функции sensor_update. Затем эта функция рассчитывает количество светодиодов, которые должны загореться, тем же методом, который мы обсуждали выше, т. Е. Разделив процент заряда батареи на 12,5, а затем беря максимальное значение. Затем он использует это значение для заполнения массива типа LedColor цветом в соответствии с текущим процентом заряда батареи. Мы используем красный цвет для процентов заряда батареи в диапазоне от 0 до 20, желтый цвет для процентов заряда батареи в диапазоне от 21 до 50 и зеленый цвет для процентов заряда батареи в диапазоне от 51 до 100.

После этого вызывается функция set_leds и передается массив LedColor для включения светодиодов.

Теперь мы готовы разместить эту программу на нашем Raspberry Pi, но перед этим нам нужно создать хост-программу, которая будет работать на нашем Raspberry Pi и постоянно следить за Васм модуль. Мы увидим, как создать хост на Raspberry pi в нашем следующем блоге. Так что следите за обновлениями.

Перед этим убедитесь, что вы скомпилировали эту программу в wasm, чтобы мы могли использовать ее и запустить индикатор батареи на Raspberry pi.

Если вы хотите прочитать больше подобного контента? Подпишитесь на информационный бюллетень Rust Times и получайте идеи и последние обновления раз в две недели прямо на свой почтовый ящик. Подпишитесь на новостную рассылку Rust Times: https://bit.ly/2Vdlld7.