#include "controller.h" #include "spi_master.h" #include "config.h" Controller::Controller(Player* p, SPIMaster* s) { _player = p; _spi = s; _rfid = new MFRC522(17, MFRC522::UNUSED_PIN); BTN_NEXT_SETUP(); BTN_PREV_SETUP(); BTN_VOL_UP_SETUP(); BTN_VOL_DOWN_SETUP(); _spi->select_rc522(); DEBUG("Initializing RC522...\n"); _rfid->PCD_Init(); #ifdef SHOW_DEBUG _rfid->PCD_DumpVersionToSerial(); #endif _spi->select_rc522(false); INFO("RC522 initialized.\n"); for (uint8_t i=0; iselect_rc522(); if (!_rfid->PICC_ReadCardSerial()) { if (!_rfid->PICC_IsNewCardPresent()) { return 0; } if (!_rfid->PICC_ReadCardSerial()) { return 0; } } _spi->select_rc522(false); uint32_t uid = _rfid->uid.uidByte[0]<<24 | _rfid->uid.uidByte[1]<<16 | _rfid->uid.uidByte[2]<<8 | _rfid->uid.uidByte[3]; return uid; } void Controller::_check_rfid() { MFRC522::StatusCode status; if (_rfid_present) { byte buffer[2]; byte buffer_size = 2; _spi->select_rc522(); status = _rfid->PICC_WakeupA(buffer, &buffer_size); if (status == MFRC522::STATUS_OK) { // Card is still present. _rfid->PICC_HaltA(); _spi->select_rc522(false); return; } _spi->select_rc522(false); // Card is now gone _rfid_present = false; INFO("No more RFID card.\n"); _player->stop(); } else { uint32_t uid = _get_rfid_card_uid(); if (uid > 0) { _mqtt_client->publish_rfid_uid(uid); //_no_rfid_card_count = 0; String temp = String(uid, HEX); String s_uid = ""; for (int i=0; i<(8-temp.length()); i++) { s_uid.concat("0"); } s_uid.concat(temp); INFO("New RFID card uid: %s\n", s_uid.c_str()); _rfid_present = true; String data = _read_rfid_data(); _player->play_id(s_uid); } } } String Controller::_read_rfid_data() { _spi->select_rc522(); DEBUG("Trying to read RFID data...\n"); String data = ""; MFRC522::MIFARE_Key key; key.keyByte[0] = 0xD3; key.keyByte[1] = 0xF7; key.keyByte[2] = 0xD3; key.keyByte[3] = 0xF7; key.keyByte[4] = 0xD3; key.keyByte[5] = 0xF7; MFRC522::PICC_Type type = _rfid->PICC_GetType(_rfid->uid.sak); uint8_t sectors = 0; switch(type) { case MFRC522::PICC_TYPE_MIFARE_MINI: sectors = 5; break; case MFRC522::PICC_TYPE_MIFARE_1K: sectors = 16; break; case MFRC522::PICC_TYPE_MIFARE_4K: sectors = 40; break; default: INFO("Unknown PICC type %s\n", String(MFRC522::PICC_GetTypeName(type)).c_str()); } for (uint8_t sector=1; sectorPCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block_offset, &key, &_rfid->uid); if (status != MFRC522::STATUS_OK) { DEBUG("PCD_Authenticate() for sector %d failed: %s\n", sector, String(_rfid->GetStatusCodeName(status)).c_str()); continue; } for (uint8_t block=0; blockMIFARE_Read(block_offset + block, buffer, &byte_count); if (status != MFRC522::STATUS_OK) { DEBUG("MIFARE_Read() failed: %s\n", String(_rfid->GetStatusCodeName(status)).c_str()); continue; } for (int i=0; i<16; i++) { if (buffer[i]>=0x20 && buffer[i]<0x7F) data.concat((char)buffer[i]); } } } _rfid->PICC_HaltA(); _rfid->PCD_StopCrypto1(); DEBUG("Data from RFID: %s", data.c_str()); _spi->select_rc522(false); return data; } void Controller::_check_serial() { 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); _serial_buffer = String(); } } else { _serial_buffer.concat(c); } } } void Controller::_execute_serial_command(String cmd) { DEBUG("Executing command: %s\n", cmd.c_str()); 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.startsWith("play ")) { _player->play_id(cmd.substring(5)); } else if (cmd.startsWith("sys ")) { _player->play_system_sound(cmd.substring(4)); } else if (cmd.equals("stop")) { _player->stop(); } else if (cmd.equals("help")) { _execute_command_help(); } else if (cmd.equals("-")) { _player->vol_down(); } else if (cmd.equals("+")) { _player->vol_up(); } else if (cmd.equals("p")) { _player->track_prev(); } else if (cmd.equals("n")) { _player->track_next(); } else if (cmd.equals("ids")) { _execute_command_ids(); } else { ERROR("Unknown command: %s\n", cmd.c_str()); } return; } void Controller::_execute_command_ls(String path) { INFO("Listing contents of %s:\n", path.c_str()); std::list files = _player->ls(path); for(std::list::iterator it=files.begin(); it!=files.end(); ++it) { INFO(" %s\n", (*it).c_str()); } } void Controller::_execute_command_ids() { for (std::map::iterator it = _player->id_to_folder_map.begin(); it!=_player->id_to_folder_map.end(); ++it) { INFO(" %s -> %s\n", it->first.c_str(), it->second.c_str()); } } void Controller::_execute_command_help() { INFO("Valid commands are:"); INFO(" help - Displays this help\n"); INFO(" ls [dir] - Lists the contents of [dir] or, if not given, of /\n"); INFO(" ids - Lists all known ID-to-folder mappings\n"); INFO(" play [id] - Plays the album with the given id\n"); INFO(" sys [file]- Plays the file as system sound\n"); INFO(" stop - Stops playback\n"); INFO(" - / + - Decrease or increase the volume\n"); INFO(" p / n - Previous or next track\n"); } void Controller::_check_buttons() { if (BTN_PREV() && _debounce_button(0)) { _player->track_prev(); } else if (BTN_VOL_UP() && _debounce_button(1)) { _player->vol_up(); } else if (BTN_VOL_DOWN() && _debounce_button(2)) { _player->vol_down(); } else if (BTN_NEXT() && _debounce_button(3)) { _player->track_next(); } } bool Controller::_debounce_button(uint8_t index) { bool ret = false; if (_button_last_pressed_at[index] + DEBOUNCE_MILLIS < millis()) { DEBUG("Button %d pressed.\n", index); ret = true; } _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()) { response.concat("\"album\": \""); response.concat(_player->album()); response.concat("\", \"track\": "); response.concat(_player->track()); response.concat(", \"position\": "); response.concat(_player->position()); response.concat(", "); } 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; } void Controller::_send_mqtt_report() { }