Massive changes. Added a quite nice webinterface with live data using WebSockets. Removed the FTP server (wasn't that useful anyways). JSON creating using ArduinoJson instead of String concatenation. Ans, and, and.
This commit is contained in:
@ -2,11 +2,15 @@
|
||||
#include "spi_master.h"
|
||||
#include "config.h"
|
||||
#include "playlist.h"
|
||||
#include "http_server.h"
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
Controller::Controller(Player* p, PlaylistManager* pm) {
|
||||
_player = p;
|
||||
_pm = pm;
|
||||
_rfid = new MFRC522(17, MFRC522::UNUSED_PIN);
|
||||
|
||||
_player->register_controller(this);
|
||||
|
||||
BTN_NEXT_SETUP();
|
||||
BTN_PREV_SETUP();
|
||||
@ -29,19 +33,28 @@ void Controller::set_mqtt_client(MQTTClient* m) {
|
||||
_mqtt_client = m;
|
||||
}
|
||||
|
||||
void Controller::register_http_server(HTTPServer* h) {
|
||||
_http_server = h;
|
||||
}
|
||||
|
||||
void Controller::loop() {
|
||||
TRACE("Controller::loop()...\n");
|
||||
unsigned long now = millis();
|
||||
if ((_last_rfid_scan_at < now - RFID_SCAN_INTERVAL) || (now < _last_rfid_scan_at)) {
|
||||
_check_rfid();
|
||||
_last_rfid_scan_at = now;
|
||||
}
|
||||
if ((_last_position_info_at < now - POSITION_SEND_INTERVAL) || (now < _last_position_info_at)) {
|
||||
send_position();
|
||||
_last_position_info_at = now;
|
||||
}
|
||||
_check_serial();
|
||||
_check_buttons();
|
||||
|
||||
if ((_last_mqtt_report_at < now - MQTT_REPORT_INTERVAL) || (now < _last_mqtt_report_at)) {
|
||||
_send_mqtt_report();
|
||||
_last_mqtt_report_at = now;
|
||||
if (_cmd_queue.length() > 0) {
|
||||
process_message(_cmd_queue);
|
||||
_cmd_queue = "";
|
||||
}
|
||||
TRACE("Controller::loop() done.\n");
|
||||
}
|
||||
|
||||
uint32_t Controller::_get_rfid_card_uid() {
|
||||
@ -60,6 +73,7 @@ uint32_t Controller::_get_rfid_card_uid() {
|
||||
}
|
||||
|
||||
void Controller::_check_rfid() {
|
||||
TRACE("check_rfid running...\n");
|
||||
MFRC522::StatusCode status;
|
||||
if (_rfid_present) {
|
||||
byte buffer[2];
|
||||
@ -91,9 +105,11 @@ void Controller::_check_rfid() {
|
||||
}
|
||||
s_uid.concat(temp);
|
||||
INFO("New RFID card uid: %s\n", s_uid.c_str());
|
||||
_last_rfid_uid = s_uid;
|
||||
_rfid_present = true;
|
||||
|
||||
String data = _read_rfid_data();
|
||||
_last_rfid_data = data;
|
||||
|
||||
Playlist* pl = _pm->get_playlist_for_id(s_uid);
|
||||
if (data.indexOf("[lock]") != -1) {
|
||||
@ -110,7 +126,15 @@ void Controller::_check_rfid() {
|
||||
return;
|
||||
}
|
||||
int index;
|
||||
if (data.indexOf("[random]") != -1 && pl->is_fresh()) {
|
||||
if (data.indexOf("[advent]") != -1 && pl->is_fresh()) {
|
||||
struct tm time;
|
||||
getLocalTime(&time);
|
||||
if (time.tm_mon == 11) { // tm_mon is "months since january", so 11 means december.
|
||||
pl->advent_shuffle(time.tm_mday);
|
||||
} else {
|
||||
// TODO
|
||||
}
|
||||
} else if (data.indexOf("[random]") != -1 && pl->is_fresh()) {
|
||||
pl->shuffle();
|
||||
} else if ((index=data.indexOf("[random:")) != -1 && pl->is_fresh()) {
|
||||
String temp = data.substring(index + 8);
|
||||
@ -133,11 +157,13 @@ void Controller::_check_rfid() {
|
||||
}
|
||||
|
||||
_player->play(pl);
|
||||
send_playlist_manager_status();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String Controller::_read_rfid_data() {
|
||||
TRACE("_read_rfid_data() running...\n");
|
||||
static MFRC522::MIFARE_Key keys[8] = {
|
||||
{{0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7}}, // D3 F7 D3 F7 D3 F7
|
||||
{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}, // FF FF FF FF FF FF = factory default
|
||||
@ -205,12 +231,14 @@ String Controller::_read_rfid_data() {
|
||||
}
|
||||
|
||||
void Controller::_check_serial() {
|
||||
TRACE("check_serial running...\n");
|
||||
|
||||
if (Serial.available() > 0) {
|
||||
char c = Serial.read();
|
||||
Serial.printf("%c", c);
|
||||
if (c==10 || c==13) {
|
||||
if (_serial_buffer.length()>0) {
|
||||
_execute_serial_command(_serial_buffer);
|
||||
process_message(_serial_buffer);
|
||||
_serial_buffer = String();
|
||||
}
|
||||
} else {
|
||||
@ -219,18 +247,19 @@ void Controller::_check_serial() {
|
||||
}
|
||||
}
|
||||
|
||||
void Controller::_execute_serial_command(String cmd) {
|
||||
bool Controller::process_message(String cmd) {
|
||||
DEBUG("Executing command: %s\n", cmd.c_str());
|
||||
|
||||
if (cmd.startsWith("play ")) {
|
||||
Playlist* p = _pm->get_playlist_for_id(cmd.substring(5));
|
||||
Playlist* p = _pm->get_playlist_for_folder(cmd.substring(5));
|
||||
_player->play(p);
|
||||
//} else if (cmd.equals("ls")) {
|
||||
// _execute_command_ls("/");
|
||||
//} else if (cmd.startsWith("ls ")) {
|
||||
// _execute_command_ls(cmd.substring(3));
|
||||
//} else if (cmd.equals("play")) {
|
||||
// _player->play_random_album();
|
||||
} else if (cmd.equals("play")) {
|
||||
_player->play();
|
||||
|
||||
} else if (cmd.equals("stop")) {
|
||||
_player->stop();
|
||||
} else if (cmd.equals("help")) {
|
||||
@ -239,16 +268,28 @@ void Controller::_execute_serial_command(String cmd) {
|
||||
_player->vol_down();
|
||||
} else if (cmd.equals("+")) {
|
||||
_player->vol_up();
|
||||
} else if (cmd.equals("p")) {
|
||||
} else if (cmd.startsWith("volume=")) {
|
||||
uint8_t vol = cmd.substring(7).toInt();
|
||||
_player->set_volume(vol);
|
||||
} else if (cmd.equals("track_prev")) {
|
||||
_player->track_prev();
|
||||
} else if (cmd.equals("n")) {
|
||||
} else if (cmd.equals("track_next")) {
|
||||
_player->track_next();
|
||||
} else if (cmd.startsWith("track=")) {
|
||||
uint8_t track = cmd.substring(6).toInt();
|
||||
_player->set_track(track);
|
||||
} else if (cmd.equals("ids")) {
|
||||
_pm->dump_ids();
|
||||
} else if (cmd.equals("reset_vs1053")) {
|
||||
_player->stop();
|
||||
_player->init();
|
||||
} else if (cmd.equals("reboot")) {
|
||||
ESP.restart();
|
||||
} else {
|
||||
ERROR("Unknown command: %s\n", cmd.c_str());
|
||||
return false;
|
||||
}
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Controller::_execute_command_ls(String path) {
|
||||
@ -272,6 +313,8 @@ void Controller::_execute_command_help() {
|
||||
}
|
||||
|
||||
void Controller::_check_buttons() {
|
||||
TRACE("check_buttons running...\n");
|
||||
|
||||
if (BTN_PREV() && _debounce_button(0)) {
|
||||
if (_state == NORMAL) {
|
||||
_player->track_prev();
|
||||
@ -300,33 +343,55 @@ bool Controller::_debounce_button(uint8_t index) {
|
||||
_button_last_pressed_at[index] = millis();
|
||||
return ret;
|
||||
}
|
||||
String Controller::get_status_json() {
|
||||
String response = String("{");
|
||||
response.concat("\"state\": \"");
|
||||
response.concat(_player->is_playing() ? "playing" : "idle");
|
||||
response.concat("\", ");
|
||||
if (_player->is_playing()) {
|
||||
// TODO
|
||||
//response.concat("\"album\": \"");
|
||||
//response.concat(_player->album());
|
||||
//response.concat("\", \"track\": ");
|
||||
//response.concat(_player->track());
|
||||
//response.concat(", \"position\": ");
|
||||
//response.concat(_player->position());
|
||||
//response.concat(", ");
|
||||
|
||||
String Controller::json() {
|
||||
DynamicJsonDocument json(1024);
|
||||
json["_type"] = "controller";
|
||||
switch(_state) {
|
||||
case LOCKED: json["state"] = "locked"; break;
|
||||
case LOCKING: json["state"] = "locking"; break;
|
||||
case NORMAL: json["state"] = "normal"; break;
|
||||
}
|
||||
response.concat("\"volume\": ");
|
||||
response.concat(_player->volume());
|
||||
response.concat(", \"volume_max\": ");
|
||||
response.concat(VOLUME_MAX);
|
||||
response.concat(", \"volume_min\": ");
|
||||
response.concat(VOLUME_MIN);
|
||||
response.concat(", \"rfid_uid\": ");
|
||||
response.concat(String(_last_rfid_card_uid, HEX));
|
||||
response.concat("}\n");
|
||||
return response;
|
||||
JsonObject rfid = json.createNestedObject("last_rfid");
|
||||
rfid["uid"] = _last_rfid_uid;
|
||||
rfid["data"] = _last_rfid_data;
|
||||
return json.as<String>();
|
||||
}
|
||||
|
||||
void Controller::_send_mqtt_report() {
|
||||
void Controller::send_player_status() {
|
||||
TRACE("In send_player_status()...\n");
|
||||
|
||||
if (_http_server->ws->count() > 0) {
|
||||
_http_server->ws->textAll(_player->json());
|
||||
_http_server->ws->textAll(_player->position_json());
|
||||
}
|
||||
}
|
||||
|
||||
void Controller::send_playlist_manager_status() {
|
||||
TRACE("In send_playlist_manager_status()...\n");
|
||||
if (_http_server->ws->count() > 0) {
|
||||
_http_server->ws->textAll(_pm->json());
|
||||
}
|
||||
}
|
||||
|
||||
void Controller::send_position() {
|
||||
TRACE("In send_position()...\n");
|
||||
if (_http_server->ws->count() > 0) {
|
||||
_http_server->ws->textAll(_player->position_json());
|
||||
}
|
||||
_last_position_info_at = millis();
|
||||
}
|
||||
|
||||
void Controller::inform_new_client(AsyncWebSocketClient* client) {
|
||||
String s;
|
||||
s += _pm->json();
|
||||
s += '\n';
|
||||
s += _player->json();
|
||||
s += '\n';
|
||||
s += _player->position_json();
|
||||
client->text(s);
|
||||
}
|
||||
|
||||
void Controller::queue_command(String s) {
|
||||
_cmd_queue = s;
|
||||
}
|
Reference in New Issue
Block a user