NEWS
ESP8266 remote control to Squeezebox server
-
Решил переставить Вашему вниманию, еще один из способов управлять Вашим плеером, кроме хардварных кнопок (у кого они есть) и WEB интерфейсов и смартфонов.
Если у Вас имеется установленные Logitech Media Server, а также один или несколько плееров подключенных к нему, то вопрос локального управления этими плеерами у Вас когда нибудь да возникнет, как возник у меня.
Дети услышат музыку играющюю в столовой, попросят что-бы у них она тоже заиграла, берешь свой телефон и добавляешь их плеер в синхногруппу (для синхроного воспроизведения) со столовой. Все наслаждаются музыкой. Но их нежелание на телефоне самим управлять громкостью и воспроизведением меня начало бесить… Как говорится сам сделал, сам и включай и выключай музыку. Чес самым озадачил себя сделать локальное управление проигрывателями описаными здесь - http://forum.iobroker.net/viewtopic.php?f=33&t=4983
Т.к с неделя понять как заставить работать с кнопками (по прерываниям) в Orange Pi прошла безуспешно, то решил взять, то с чем у меня когда-то получалось это делать. Тем более в наличии еще и целая горсть ESP8266-12E.
Пока все параметры задаются в скетче, но постепенно буду дописывать и переделывать, что-бы можно было указать параметры wifi, сервер и плеер через WEB сервер ESP-шки. А в дальнейшем можно будет сделать и через меню на OLED дисплее с сохранем этих данных во Flash памяти.
Беглое изучение управления CLI (http://адрес_вашего_сервера:9000/html/docs/cli-api.html) привело к появлению на свет первого варианта вполне рабочего кода:
! ```
`#include <esp8266wifi.h>
#include <rotary.h> // Rotary-master https://github.com/brianlow/Rotary
#include <onebutton.h> // OneButton https://github.com/mathertel/OneButton
#include <wire.h> // Only needed for Arduino 1.6.5 and earlier
#include "SSD1306.h" // SSD1306 https://github.com/squix78/esp8266-oled-ssd1306
! Rotary encoder = Rotary(D1, D2); // Выход энкодера GPIO5 и GPIO4
OneButton button(D5, true); // Кнопка энкодера GPIO 14
SSD1306 display(0x3c, D3, D4); // D3 (GPIO0) и D4 (GPIO2)
! const char* ssid = "";
const char password = "***";
! const char server = "192.168.11.1";
const int port = 9090;
! int power = 0;
int vol = 0;
! //String player = "00%3A00%3A00%3A00%3A00%3A1f";
String player = "aa%3Aaa%3A5e%3A01%3Ad1%3A02";
! WiFiClient client;
! void connectWifi() {
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());display.clear();
display.setFont(ArialMT_Plain_10);
display.setTextAlignment(TEXT_ALIGN_CENTER_BOTH);
display.drawString(DISPLAY_WIDTH/2, DISPLAY_HEIGHT/2, "Ready to work:\n" + WiFi.localIP().toString());
display.display();
}! // Подпрограмма передачи команды на сервер
void clitx(String cmd) {
Serial.print("Send to LMS: ");
Serial.print(player + " " + cmd + "\r\n");
// This will send the request to the server
client.print(player + " " + cmd + "\r\n");
}
! // Подпрограмма обработки одиночного нажатия
void ClickFunction() {
Serial.println("Click.");
clitx("mode play");
digitalWrite(D6, 1);
delay(5);
digitalWrite(D6, 0);
}
! // Подпрограмма обработки двойного нажатия
void DoubleclickFunction() {
Serial.println("Doubleclick..");
if (power) {
clitx("mode pause");
digitalWrite(D6, 1);
delay(5);
digitalWrite(D6, 0);
}
}
! // Подпрограмма обработки долгого удержания
void LongPressStartFunction() {
Serial.println("LongPress start");
! digitalWrite(D6, 1);
delay(5);
digitalWrite(D6, 0);if (!power){
clitx("power 1");
power=1;
return;
}if (power) {
clitx("power 0");
power=0;
return;
}}
! // Подпрограмма обработки удержания (не используется пока)
void LongPressFunction() {
Serial.println("LongPress...");}
! // Подпрограмма обработки отпускания после долгого удержания (не используется пока)
void LongPressStopFunction() {
Serial.println("LongPress stop");
}
! // Подпрограмма обработки вращения против направления движения часовой стрелки
void LeftRotation() {
Serial.println("LeftRotation.");
if (power) {
clitx("mixer volume -1");
digitalWrite(D6, 1);
delay(5);
digitalWrite(D6, 0);
}
}
! // Подпрограмма обработки вращения по направлению движения часовой стрелки
void RightRotation() {
Serial.println("RightRotation.");
if (power) {
clitx("mixer volume +1");
digitalWrite(D6, 1);
delay(5);
digitalWrite(D6, 0);
}
}
! // Подпрограмма подписывания и получния текущих значений
void clisubscribe(){
delay(100);
client.connect(server, port);
delay(100);
//clitx("subscribe mode"); // подписываемся на оповещение об изменении статуса
//delay(10);
clitx("subscribe mixer,power,pause,play,stop"); // подписываемся на оповещение об изменении статуса
delay(10);
clitx("mixer volume ?"); // получаем текущие параметры
delay(10);
clitx("power ?");
delay(10);
clitx("mode ?");
delay(10);
clitx("playlist index ?");
delay(10);
}
! void drawProgressBarVolume(int vol) {
display.clear();
//int vol = (vol / 5) % 100;
// draw the progress bar
display.drawProgressBar(0, 51, 127, 12, vol);
! // draw the percentage as String
display.setTextAlignment(TEXT_ALIGN_CENTER);
display.drawString(10, 30, "Громкость " + String(vol) + "%");
display.display();
}
! void setup() {
! power = 0; // присdаиваем питанию временное значение 0pinMode(D8, OUTPUT); //POWER - Red led (статус питания плеера)
pinMode(D6, OUTPUT); //TX to LMS - Green led (вспыхивает когда передается команда на сервер)Serial.begin(115200);
Serial.println("Power ON...");
Serial.println ("Connect to Router requested");! display.init();
display.flipScreenVertically();
display.setContrast(255);
display.setFont(ArialMT_Plain_10);
! connectWifi(); // signal WiFi connected
! Serial.print("Free Heap[b]: ");
Serial.println(ESP.getFreeHeap());
! // give the WiFi a second to initialize:
delay(500);
! Serial.print("connecting to ");
Serial.print(server);
Serial.print(":");
Serial.println("9090");
! if (!client.connect(server, port)) {
Serial.println("connection failed");
return;
}
Serial.println("connection OK");
delay(10);
! clisubscribe();
delay(100);
client.println();
delay(200);
if (client.available()) Serial.println("CLI available...");digitalWrite(D6, LOW);
digitalWrite(D8, LOW);! button.attachClick(ClickFunction);
button.attachDoubleClick(DoubleclickFunction);
button.attachLongPressStart(LongPressStartFunction);
//button.attachLongPressStop(LongPressStopFunction);
//button.attachDuringLongPress(LongPressFunction);
! //vol = 0;
//drawProgressBarVolume(vol);}
! void loop() {
! button.tick();unsigned char rotary = encoder.process();
if (rotary == DIR_NONE) {
// do nothing
}
else if (rotary == DIR_CW) {
LeftRotation();
}
else if (rotary == DIR_CCW) {
RightRotation();
}! while(client.available()){
String clirx = client.readStringUntil('\r\n');
Serial.println("Recieving: " + clirx);if ( clirx == (player + " power 1 \r") || clirx == (player + " power 1\r") || clirx == (player + " power 1 1\r")) { digitalWrite(D8, HIGH); power = 1; } if ( clirx == (player + " power 0 \r") || clirx == (player + " power 0\r")) { digitalWrite(D8, LOW); power = 0; } if (clirx.startsWith(player + " mixer volume")) { Serial.println("Change mixer volume " + clirx.substring(41)); if (clirx.substring(41).startsWith("-")) { Serial.println("Volume -" + clirx.substring(42)); if (vol >= 0) vol = vol-clirx.substring(42).toInt(); if (vol < 0) vol =0; drawProgressBarVolume(vol); } if (clirx.substring(41).startsWith("%2B")) { Serial.println("Volume +" + clirx.substring(44)); if (vol <= 100) vol = vol+clirx.substring(44).toInt(); if (vol > 100) vol = 100; drawProgressBarVolume(vol); } if (!clirx.substring(41).startsWith("-") && !clirx.substring(41).startsWith("%2B")) { Serial.println("Volume set to " + clirx.substring(41)); vol = clirx.substring(41).toInt(); drawProgressBarVolume(vol); } } // еще можно анализировать ответы...
}
String clirx="";!
// проверка что есть соединение, если нет, то перезапуск
if (client.connected() != 1 || WiFi.status() != WL_CONNECTED)
{
Serial.print("Reconnect to CLI ");
client.connect(server, port);
while (!client.connect(server, port)) {
delay(500);
Serial.print(".");
}
Serial.println();
Serial.println("Reconnect OK.");
//ESP.reset();
clisubscribe();
}
// идем дальше...! }</wire.h></onebutton.h></rotary.h></esp8266wifi.h>`
Для отладки использовал платку "ESP8266 Witty Cloud".
! По тексту есть коментарии так, что можно понять как работает.
! Пока работает так:
! Включение/выключение - долгое удержание кнопки
! Играть - короткое нажатие на кнопку
! Пауза - двойное нажатие
! Громкость +1 или -1 - крутилка энкодера (можно изменить на +-2,3,5 %)
! Причем громкость передается только если состояние питания у проигрывателя - включено.
! Будет добавлено еще 2 кнопки вперед и назад (это команды "playlist index +1" и "playlist index -1")
! Ну и постараюсь добавить управление по MQTT.
! Понимаю, что много необходимо оптимизировать, а может и условия проверять по другому, но пока сделал так, как умею.[/b] -
В чем у меня есть трудности с добавлением дисплея для отображения информации, то это вот в чем:
При старте модуля мы подписываемся на изменения громкости и получаем ее текущее состояние, в ответ получаем
Recieving: 00%3A00%3A00%3A00%3A00%3A1f mixer volume 34
текущюю громкость с сервера, нам необходимо запомнить значение 34 в пременой vol.
Получая состояние громкости, оно приходит в виде текстовой строки
Recieving: 00%3A00%3A00%3A00%3A00%3A1f mixer volume %2B1 Recieving: 00%3A00%3A00%3A00%3A00%3A1f mixer volume %2B2 Recieving: 00%3A00%3A00%3A00%3A00%3A1f mixer volume %2B2 Recieving: 00%3A00%3A00%3A00%3A00%3A1f mixer volume %2B2 Recieving: 00%3A00%3A00%3A00%3A00%3A1f mixer volume -2 Recieving: 00%3A00%3A00%3A00%3A00%3A1f mixer volume -2 Recieving: 00%3A00%3A00%3A00%3A00%3A1f mixer volume -2 Recieving: 00%3A00%3A00%3A00%3A00%3A1f mixer volume -2 Recieving: 00%3A00%3A00%3A00%3A00%3A1f mixer volume 60 Recieving: 00%3A00%3A00%3A00%3A00%3A1f mixer volume 30 Recieving: 00%3A00%3A00%3A00%3A00%3A1f mixer volume 70
В дальнейшем при приеме команд мы должны или прибавлять (если mixer volume %2B2) или убавлять (если mixer volume -2) текущее значение vol. А если получен (mixer volume 30), то задаеть ей это значение.
Пока не пойму как из принятой строки String забрать значение громкости и поместить ее числовую переменную, что бы можно было потом отображать на дисплее.
Ох… Разобрался... Может и коряво, но работает...
if (clirx.startsWith(player + " mixer volume")) { Serial.println("Change mixer volume " + clirx.substring(41)); if (clirx.substring(41).startsWith("-")) { Serial.println("Volume -" + clirx.substring(42)); if (vol >= 0) vol = vol-clirx.substring(42).toInt(); if (vol < 0) vol =0; drawProgressBarVolume(vol); } if (clirx.substring(41).startsWith("%2B")) { Serial.println("Volume +" + clirx.substring(44)); if (vol <= 100) vol = vol+clirx.substring(44).toInt(); if (vol > 100) vol = 100; drawProgressBarVolume(vol); } if (!clirx.substring(41).startsWith("-") && !clirx.substring(41).startsWith("%2B")) { Serial.println("Volume set to " + clirx.substring(41)); vol = clirx.substring(41).toInt(); drawProgressBarVolume(vol); } }
Обновил код с поддержкой OLED SSD1306.
PS: Очень хочется русского шрифта для библиотеки SSD1306 https://github.com/squix78/esp8266-oled-ssd1306
-
Привет. Уже неделю вынашиваю точно такую же идею. Только в моих планах было использовать еще ардуину как прослойку между экраном и ESP, а также поручить ей будить ESP из слип режима, для экономии питания. Идея была оформить в виде пульта с экраном от нокии.
Но моя проблема, в программировании я не очень, а с ESP8266 только начал общаться, писать сам прошивку еще не пробовал.
-
PS: Очень хочется русского шрифта для библиотеки SSD1306 https://github.com/squix78/esp8266-oled-ssd1306 `
Сам отвечу…Вот конвертер шрифтов для этой библиотеки... https://github.com/arcao/esp8266-oled-s ... nt-creator
Сконвертировать можно любой шрифт установленный у Вас в компьютере и под любой размер!!!
-
@msapogov Добрый вечер.Скажите пожалуйста доделать пульт дистанционного управления ESP8266 для сервера Squeezebox какой хотели?
-
@msapogov Добрый вечер.Скажите пожалуйста сделали пульт дистанционного управления ESP8266 для сервера Squeezebox какой хотели?
-
@евгений-рудаков said in ESP8266 remote control to Squeezebox server:
@msapogov Добрый вечер.Скажите пожалуйста сделали пульт дистанционного управления ESP8266 для сервера Squeezebox какой хотели?
Взять код из первого сообщения , подставить свои значения , и скомпилировать в Arduino IDE.
-
@msapogov Ок. Спасибо.