oneDevice.js
Используйте NodeJS для управления оборудованием.
«device» был занят, поэтому пришлось назвать его «onedevice». Это чувство… 🙄
Что это?
Это пакет драйверов для оборудования, управляемый с помощью NodeJS. Он готов к использованию, имеет полную документацию, постоянно обновляется и имеет дружественный API. Используйте Raspberry Pi для создания собственного умного дома.
Последние обновления
v0.0.3 @ 2018-06-02 22:56
Сообщить об ошибке
Основные обновления в будущем
В папке test есть примеры тестов, которые прошли успешно на моей платформе Linux raspberrypi 4.4.34-v7+ Raspbian GNU/Linux 8.0 (jessie).
Обязательно к прочтению
Можно импортировать все модули или использовать только один модуль.
var Device = require('onedevice');
var XFS5152CE = require('onedevice/lib/device/xfs5152ce');
new Device(option);
description
: String
Описание этого устройства. Значение по умолчанию: String('this device has not description')
model
: String
Конкретная модель этого устройства. Если эта опция настроена, то соответствующий драйвер оборудования будет возвращён на основе модели. Если device
не имеет драйвера для этой модели, возвращается null.
На данный момент драйверы устройств, интегрированные в device
, включают:
interface
: String
Общий способ связи для этого универсального устройства. Эта опция подходит для создания пользовательского драйвера устройства или когда device
не интегрировал устройство. Например, при использовании микроконтроллера STC89C52RC с последовательным интерфейсом для связи с Raspberry Pi, вы можете создать последовательный драйвер, который позволит вам обмениваться данными с микроконтроллером, а затем самостоятельно расширить логику приложения.
Для большинства датчиков или модулей используются распространённые протоколы связи, такие как i2c, uart, spi и one-wire. Управление этими устройствами относительно просто, поскольку вам не нужно разбираться в принципах этих протоколов, а нужно только обрабатывать отправку и получение данных.
Драйверы для большинства распространённых датчиков и модулей создаются с использованием последовательного протокола, а затем реализуются функции say, sleep, setVolume и т. д.
Протоколы связи, используемые в настоящее время в device
:
address
: String || Int
Физический адрес интерфейса или логический адрес I2C ведомого устройства этого оборудования. Если это устройство использует последовательный протокол, оно представляет собой физический адрес устройства на хосте. Например, USB-преобразователь последовательного порта, его значение может быть строкой /dev/ttyUSB0
.
Если это устройство использует протокол I2C, его значением является логический адрес этого I2C устройства. Например, значение модуля SSD1306 может быть Int0x3C
, обычно использующим шестнадцатеричное представление, хотя десятичное представление также возможно.
device
: String
Логический адрес устройства I2C на хосте. I2C устройство использует два адреса для идентификации: первый — физический адрес интерфейса, второй — логический адрес ведомого I2C. Зачем нужны два адреса? Потому что Raspberry Pi предоставляет два физических интерфейса I2C, и device
должен знать, какой интерфейс подключён к вашему устройству.
Он имеет следующие два значения:
Вы можете использовать инструмент i2cdetect
для сканирования всех устройств I2C, подключённых к шине, и вывода их логических адресов. Перед использованием инструмента необходимо установить его.
Модуль XFS5152CE может использовать I2C, SPI, последовательный порт и другие способы связи. Для питания требуется 3,3 В, и я использую модуль XFS5152CE от магазина Taobao с 3 Вт усилителем мощности.
Здесь используется последовательный порт для связи, скорость передачи данных обычно составляет 9600 бод, и она настраивается в соответствии с вашей ситуацией.
var Device = require('onedevice');
var xfs5152ce = new Device({
description: 'xfs5152ce module',
model: 'xfs5152ce',
baudRate: 9600,
address: '/dev/ttyUSB0'
});
Приведённый выше код возвращает экземпляр последовательного драйвера, а параметр address
указывает на последовательный порт. Почему используется последовательный порт? Потому что мы используем последовательный порт для управления чипом. Вам нужно дождаться успешного открытия последовательного порта перед использованием чипа.
xfs5152ce.on('open', function(next){
xfs5152ce.say('你好,科大讯飞!');
next();
});
xfs5152ce.on('error', function(error, next){
console.log(error);
next();
});
Рекомендуется использовать последовательные функции в обратном вызове события open. После запуска обратного вызова события open вы можете отправлять текст любой длины на чип для чтения вслух.
Функция say автоматически управляет очередью чтения вслух. Если текущий текст не прочитан полностью, повторный вызов функции say поместит его в очередь, и после прочтения всего текста из очереди он будет автоматически извлечён.
События open, error и data поддерживают промежуточное ПО, которое аналогично промежуточному ПО express. Метод next означает следующий промежуточный уровень, который поддерживает параметры, указывающие на изменение данных, передаваемых следующему промежуточному уровню. Пожалуйста, посмотрите на следующий пример.
// Предположим, что данные, возвращаемые последовательным портом, равны data === 1
xfs5152ce.on('data', function(data, next){
console.log('md-1-start: ', data);
next(data + 1);
console.log('md-1-end: ', data);
}).on('data', function(data, next){
console.log('md-2-start: ', data);
next();
console.log('md-2-end: ', data);
}).on('data', function(data, next){
console.log('md-3-start: ', data);
next();
console.console.log('md-3-end: ', data);
});
Результат выполнения следующий:
md-1-start: 1
md-2-start: 2
md-3-start: 1
md-3-end: 1
md-2-end: 2
md-1-end: 1
``` **XFS5152CE драйвер реализует следующие функции:**
* Функция say(text, immediately, callback)
* @params {String} text: обязательно. Текст для чтения вслух. Может содержать текстовые управляющие метки.
* @params {Boolean} immediately: опционально. Следует ли немедленно читать текст вслух. Если true, то текущая команда чтения будет прервана.
* @params {function} callback: опционально. Функция обратного вызова после успешного выполнения команды чтения текста вслух.
Функция say() предназначена для быстрого чтения текста вслух. Драйвер реализует механизм кэширования команд чтения, что позволяет хост-системе многократно вызывать функцию чтения и затем обрабатывать другие задачи. Драйвер автоматически читает все команды чтения в порядке их поступления. Если immediately равно true, то чтение текущего текста будет остановлено, и текст text будет прочитан вслух.
* Функция setVolume(volume)
* @params {integer} volume: устанавливает громкость чтения. Не влияет на текущий читаемый текст.
Устанавливает громкость чтения текста. Допустимые значения — целые числа от 1 до 10 включительно. 1 соответствует минимальной громкости, а 10 — максимальной. По умолчанию громкость равна 3. После установки громкости она будет влиять только на последующие команды чтения, но не на текущий читаемый текст. В будущем планируется реализовать возможность динамической настройки громкости.
* Функция getVolume()
* @return {integer}
Возвращает текущую громкость чтения.
* Функция sleep(callback)
* @params {function} callback: функция обратного вызова после перехода в режим пониженного энергопотребления.
Переводит чип в режим пониженного энергопотребления. После отправки команды перехода в этот режим чип немедленно прекращает выполнение всех команд, при этом его рабочий ток составляет 5 мА.
* Функция wakeup(callback)
* @params {function} callback: функция обратного вызова после выхода из режима пониженного энергопотребления.
Позволяет чипу вернуться в режим ожидания синтеза звука. При переходе в этот режим драйвер автоматически начинает читать вслух все непрочитанные команды.
* Функция voiceLength()
* @return {integer}
Возвращает количество непрочитанных команд синтеза звука. Каждая вызванная функция say увеличивает количество команд на одну.
* Функция isBusy()
* @return {boolean}
Проверяет, занят ли чип чтением текста вслух.
* Функция on(type, callback)
* @params {string} type: тип отслеживаемого события, может быть data, open или error.
* @params {function} callback: функция, которая должна выполняться при возникновении события.
Регистрирует функцию обратного вызова для указанного события. Когда событие происходит, выполняется функция обратного вызова. Можно использовать цепочку вызовов. Используется модель, похожая на onion (луковица) в express.
Для разных типов событий параметры функции обратного вызова различаются:
— data: function(data, next) — data содержит данные, полученные или переданные через промежуточное ПО.
— open: function(next).
— error: function(error, next) — error содержит информацию об ошибке.
**DHT11, DHT22, AM2302 устройства**
Эти устройства просты в использовании и подключаются к Raspberry Pi с помощью однолинейного интерфейса. Для подключения достаточно одного кабеля данных и двух кабелей питания, подключённых к положительной и отрицательной клеммам соответственно. Также можно использовать только кабель данных для считывания и передачи данных, получая питание от этого же кабеля. Более подробную информацию о схеме паразитного питания можно найти в документации по однолинейному интерфейсу.
```js
var dht11 = new Device({
model: 'dht11',
description: 'dht11 sensor',
address: 4
});
Адрес представляет собой номер GPIO, к которому подключён датчик. Используется нумерация BCM GPIO.
dht11.fetch(function(error, temperature, humidity){
if (error) {
console.log(error.message);
}else{
console.log('Температура: ' + temperature + ' Влажность: ' + humidity);
}
});
Считывание данных с датчика выполняется просто. Обратите внимание, что DHT11 имеет период выборки 1 секунду, рекомендуется делать паузу не менее 1 секунды между последовательными чтениями, чтобы избежать ошибок. DHT22 имеет период выборки 2 секунды, рекомендуется делать паузу не менее 2 секунд между последовательными чтениями.
В датчиках серии DHT теперь используется RxJS. Метод observe возвращает объект наблюдателя.
// Наблюдение за датчиком DHT11 каждые 2 секунды
var observable = dht11.observe(2000);
observable является подписчиком, который можно получить с помощью метода then. Подписка возвращает subscription, представляющую выполняющуюся операцию.
var subscription = observable.then(function(value){
// Успешная подписка на считывание данных датчика
console.log(value);
// Эта подписка будет выполняться каждые 2 секунды после подписки, так как это было указано в методе observe
subscription.dispose();
}, function(error){
// Ошибка при считывании данных датчика
console.log(error);
// Подписка автоматически прекращается после ошибки
});
Используя RxJS, мы можем легко комбинировать различные условия с операторами, что делает нашу логику более понятной.
// наблюдение может указывать тип данных, t означает температуру, h означает влажность, если не указано, то будут наблюдаться и температура, и влажность
var subscription = dht11.observe(2000, 't').max(28).then(function(value){
console.log('Очень жарко! Текущая температура: ', value);
});
var subscription1 = dht11.observe(2000, 'h').min(20).then(function(value){
console.log('очень сухо! текущая влажность: ', значение);
});
max и min являются операторами. Операторы могут быть связаны друг с другом, и они выполняются в определённом порядке. Они похожи на секции трубопровода, соединённые последовательно.
max означает больше (значение > max), и подписка будет выполнена, когда температура превысит 28 градусов.
min означает меньше (значение < min), и подписка будет выполнена, когда влажность станет меньше 20.
Кроме того, существуют и другие операторы, такие как равно when(condi) и диапазон between(left, right). Кроме того, observable включает все доступные операторы RxJS.
OLED-дисплей SSD1306
Подходит для распространённых OLED-дисплеев с основным контроллером SSD1306 и разрешением до 128x128. Разрешение выше 128x128 не тестировалось. Базовый драйвер использует пакет npm oled-ssd1306-i2c, который может управлять всеми устройствами, поддерживаемыми этим пакетом.
var ssd1306 = new Device({
description: 'ssd1306',
width: 128,
height: 64,
address: 0x3c,
device: '/dev/i2c-1'
});
width и height представляют разрешение дисплея по ширине и высоте соответственно. Адрес — это адрес I2C подчинённого устройства, который зависит от аппаратного обеспечения. Устройство — это интерфейс I2C, к которому подключено устройство, которое также зависит от оборудования. Для OLED-дисплеев SPI в настоящее время нет интегрированного драйвера, который будет добавлен позже.
Теперь давайте рассмотрим, как управлять содержимым экрана дисплея.
ssd1306.drawPNG('path/to/image.png', false, function(error){
if (error) {
console.log(error);
} else {
console.log('Отображение изображения PNG завершено');
}
});
Обратите внимание, что поддерживается только формат PNG. Чтобы достичь наилучшего эффекта отображения, разрешение изображения PNG должно соответствовать разрешению OLED-экрана. OLED отображает только один цвет, поэтому при отображении изображение будет преобразовано в одноцветное изображение, а затем отображено. Пиксели с цветом будут подсвечены, а прозрачные пиксели будут затемнены.
var Canvas = require('canvas');
var canvas = new Canvas(128, 64);
var ctx = canvas.getContext('2d');
ctx.fillStyle = '#FFF';
ctx.fillText("Hello world", 0, 0);
// Вышеприведённые 5 строк кода, вероятно, не требуют пояснений. Все они являются операциями canvas. **Результаты таковы: в canvas в левом верхнем углу будет отображаться строка «hello world» белого цвета**
// Затем содержимое canvas будет выведено на экран
ssd1306.drawCanvas(canvas);
На экране вы должны увидеть строку «hello world». Функция drawCanvas будет рисовать пиксели с canvas один за другим на экране (конечно, поддерживается рисование только указанной части canvas). Таким образом, то, что отображается на вашем canvas, будет отображаться и на экране. Вы можете управлять экраном, постоянно обновляя canvas и вызывая функцию drawCanvas в подходящий момент для обновления экрана.
Нет необходимости объяснять преимущества использования canvas — это просто и имеет обширную документацию и множество руководств, а также различные мощные библиотеки canvas.
Следует отметить, что для достижения наилучшего эффекта отображения разрешение canvas должно соответствовать разрешению экрана, и рекомендуется использовать одноцветный canvas для рисования (#FFF). Поскольку ваш OLED-дисплей является одноцветным, он не может отображать цвета. Хотя существуют цветные OLED-дисплеи, они ещё не имеют встроенного драйвера. В будущем будут интегрированы более крупные цветные LCD и TFT-экраны с драйверами. Это большой проект, и я надеюсь, что инженеры, разбирающиеся в этой области, помогут мне.
Для использования canvas в node сначала необходимо установить его. API в браузере HTML5 немного отличается от API в node. Пожалуйста, ознакомьтесь с документацией и установите его самостоятельно.
Как уже говорилось ранее, это основано на обёртке oled-ssd1306-i2c
. Она сама по себе предоставляет простой графический API для управления экраном. Например, обычное рисование пикселей, линий, прямоугольников, кругов и текста. Преимущество использования этого заключается в том, что вам не нужно устанавливать node-canvas и нет зависимостей. Он лёгкий и простой в использовании. Как его использовать?
Все API этого графического интерфейса доступны через свойство oled
экземпляра драйвера. Например:
ssd1306.oled.drawLine(1, 1, 128, 64, 1);
Приведённый выше код использует встроенный API для рисования линии от (1, 1) до (128, 64). Свойство oled — это экземпляр oled-ssd1306-i2c
. Пожалуйста, обратитесь к его документации для получения дополнительной информации о других API.
В настоящее время у драйвера SSD1306 для node есть недостаток — частота обновления слишком низкая, достигая максимум 10 кадров на моей Raspberry Pi 3B. При использовании Python можно достичь 30 кадров в секунду. Если использовать C++, то можно легко достичь 60 кадров в секунду. Сейчас я пытаюсь улучшить частоту обновления.
@params {Canvas} canvas: canvas, который нужно нарисовать.
@params {Object} config: Необязательно. Конфигурация области, которую нужно нарисовать на canvas. По умолчанию область начинается с левого верхнего угла и имеет тот же размер, что и экран. У неё есть следующие свойства:
{
sx: координата x начала рисования.
sy: координата y начала рисования
sw: ширина прямоугольника для рисования
sh: высота прямоугольника для рисования
}
Скопируйте пиксели canvas один за другим и отобразите их на экране. Используйте ctx.getImageData для получения информации о пикселях canvas. Перед рисованием пиксели, которые могут быть цветными, будут обработаны. Рекомендуется использовать #FFF для рисования. Цветные пиксели будут выделены, остальные будут отключены.
@params {string} filename: путь к PNG-изображению, которое нужно нарисовать.
@params {boolean} dither: необязательно. Следует ли включать алгоритм сглаживания при обработке пикселей изображения, по умолчанию false.
@params {function} callback: функция обратного вызова после завершения рисования изображения. Если при рисовании возникает ошибка, функция обратного вызова передаст error. Если всё пройдёт успешно, она вернёт null.
Рисует изображение PNG на экране. Чтобы добиться наилучшего эффекта отображения, изображение PNG должно быть одноцветным и прозрачным. Алгоритм сглаживания использует пакет npm floyd-steinberg
.
@params {Number} second: интервал обновления экрана в секундах. Если он не указан или равен 0, информация будет показана только один раз. В противном случае она будет автоматически обновляться каждые несколько секунд.
Отображает информацию о системе, включая статистику использования ЦП и памяти, IP-адрес и время. Если указано время, оно будет автоматически обновляться через определённые промежутки времени.
Останавливает обновление информации о системе.
Последовательные порты очень распространены и просты в использовании. Создать последовательное устройство очень просто. Самый простой способ использовать последовательный порт на Raspberry Pi — купить USB-преобразователь, например, ST-Link V2, который стоит всего около 10 долларов и поставляется с интерфейсами 3,3 В и 5 В.
var stc89c52rc = new Device({
description: 'stc89c52rc',
interface: 'serial',
address: '/dev/ttyUSB0',
baudRate: 9600
});
Это пример использования USB-конвертера и последовательного порта микроконтроллера. Микроконтроллер устанавливает скорость передачи данных, Raspberry Pi и микроконтроллер могут обмениваться данными. Последовательный порт основан на популярном пакете npm serialport
. Свойство serial экземпляра последовательного устройства — это объект serialport
, который содержит все методы и свойства. Вы можете ознакомиться с его документацией.
У экземпляра последовательного порта есть следующие методы:
Пожалуйста, обратитесь к документации XFS5152CE.
@params {buffer || array} data: данные для отправки. Может быть buffer или array, конечно, также может быть строкой, отправляемой в виде двоичного потока.
@params {function} callback: обратный вызов после успешной отправки данных. Если отправка не удалась, error будет передан через параметр.
Отправляет данные на последовательное устройство. Данные отправляются в виде двоичных потоков.
@params {string} name: имя драйвера.
@params {function} driver: метод реализации драйвера.
Регистрирует пользовательский драйвер для универсального устройства. Фактически, создайте свойство с именем name в экземпляре и назначьте ему функцию driver. Таким образом, экземпляр может напрямую вызывать эту функцию. Единственное отличие состоит в том, что this функции driver указывает на этот экземпляр. Например, XFS5152CE регистрирует драйвер следующим образом:
serial.driver('say', function(text, imed, cb){
......
}
I2C немного сложнее, потому что это пара устройств. Чтение и запись данных контролируются хостом. Raspberry Pi имеет встроенный интерфейс I2C, поэтому дополнительное оборудование не требуется. Многие модули также используют протокол I2C, например, широко используемый AT24C02 CMOS EEPROM. Учебник по микроконтроллерам часто использует этот пример для изучения операций I2C.
var i2c = new Device({
description: 'test i2c',
interface: 'i2c',
address: 0x3c,
device: '/dev/i2c-1'
});
Обратите внимание, что адрес address шины I2C не относится к физическому адресу интерфейса, а относится к логическому адресу подчинённого устройства. Адрес device относится к физическому интерфейсу. Драйвер I2C основан на очень популярном пакете npm i2c. Свойство i2c экземпляра — это объект i2c, который содержит все его методы и свойства, вы можете обратиться к его документации. SSD1306 использует универсальный драйвер I2C для управления дисплеем.
Экземпляр I2C имеет следующие методы:
См. документацию по driver выше.
Поскольку методов I2C слишком много, здесь они не инкапсулируются, и вы можете получить доступ ко всем функциям через свойство i2c.
Некоторые продвинутые модули используют сеть для обмена данными. Например, ESP 8266 WiFi-модуль может отправлять данные последовательного порта через WiFi с использованием протоколов UDP или TCP. Это становится интереснее. Подключив 8266 к последовательному порту микроконтроллера, микроконтроллер может легко подключаться к сети. Пусть микроконтроллеры собирают данные и отправляют их на Raspberry Pi через сеть или пусть Raspberry Pi отправляет команды управления для удалённого управления микроконтроллером. Самым простым способом использования 8266 является использование UDP.
var esp = new Device({
description: 'stc89c52rc-wifi',
interface: 'udp',
type: 'udp4',
address: '127.0.0.1',
port: 8266,
remoteAddress: '192.168.1.80',
remotePort: 8266,
reuseAddr: false
});
``` **Использование UDP**
Для использования UDP необходимо настроить адрес и порт локального сервера для прослушивания, а также указать IP-адрес и порт другой стороны. Обычно для модуля 8266 задают фиксированный IP.
**Примеры использования драйвера UDP:**
1. Функция: on(type, callback).
* @params {string} type: тип события. Может принимать значения: listening, close, error, message.
* @params {function} callback: функция обратного вызова при возникновении события. Для разных типов событий есть разные параметры. Подробнее:
* @type: listening — происходит после запуска локального сервера прослушивания. Параметров нет.
* @type: close — происходит при закрытии локального сервера прослушивания. Параметров нет.
* @type: error — происходит при ошибке на сервере прослушивания. callback(error).
* @type: message — происходит при получении данных сервером. callback(data, remote, next).
* data — полученные данные. Тип buffer.
* remote — встроенный объект node dgram. См. документацию node.
* next — см. документацию по драйверу xfs5152ce.
2. Функция: write(data, callback).
* @params {buffer} data: данные для отправки.
* @params {function} callback(error): функция обратного вызова после успешной или неудачной отправки данных.
3. Функция: driver(name, driver).
См. документацию по driver.
-------------------------------------------
Есть много недоработок, которые нужно исправить. Это касается как дизайна API, так и организации кода. В будущем планируется добавить больше драйверов и улучшить функциональность универсальных драйверов. Большинство драйверов основаны на универсальных устройствах, а затем адаптируются под требования оборудования и формат передачи данных для обеспечения работы оборудования. Поэтому важно улучшить функциональность универсальных драйверов.
Также в планах создать более дружественную документацию API.
В целом, это только начало.
Главное, чтобы вам было удобно пользоваться, ведь я делаю это для себя.
----------------------------------------------------
<h2 style="color: #2493fb;">change log</h2>
> v0.0.3 @ 2018-06-02 22:56
- Использование RxJS, более абстрактный и простой в использовании API.
> v0.0.2 @ 2018-04-22 17:19
- SSD1306: добавлена функция showSystemInfo для мониторинга системной информации.
- Вызов showSystemInfo напрямую отображает информацию о памяти, статистике CPU, IP и времени на экране.
- stopSystemInfo останавливает обновление информации о системном мониторинге.
- Добавлена справочная схема GPIO-контактов для поиска номеров и функций контактов Raspberry Pi.
> v0.0.1 @ 2018-01-01 23:27
- Добавлен драйвер для чипа XFS5152CE от FeiXin для преобразования текста в речь.
- Добавлен драйвер OLED-экрана SSD1306.
- Поддержка прямого рисования canvas на экране SSD1306, улучшенный графический API (я стараюсь максимально увеличить частоту обновления).
- Включает драйверы UART, I2C и UDP.
- Включает драйверы датчиков температуры и влажности DHT-11 и DHT-22.
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Комментарии ( 0 )