Connect to the internet and play songs from a web app
Dependencies: mbed Socket lwip-eth lwip-sys lwip
main.cpp
- Committer:
- maclobdell
- Date:
- 2016-05-18
- Revision:
- 0:f7c60d3e7b8a
File content as of revision 0:f7c60d3e7b8a:
/* * Copyright (c) 2015 ARM Limited. All rights reserved. * SPDX-License-Identifier: Apache-2.0 * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "mbed.h" // this tells us to load mbed OS related functions #include "tones.h" // list of all the tones and their frequencies #include "simpleclient.h" #include <string> #include <sstream> #include <vector> Serial output(USBTX, USBRX); PwmOut buzzer(D3); // our buzzer is a PWM output (pulse-width modulation) static int BPM = 35; EthernetInterface eth; // These are example resource values for the Device Object struct MbedClientDevice device = { "Manufacturer_String", // Manufacturer "Type_String", // Type "ModelNumber_String", // ModelNumber "SerialNumber_String" // SerialNumber }; // Instantiate the class which implements LWM2M Client API (from simpleclient.h) MbedClient mbed_client(device); // this is our function that plays a tone. // Takes in a tone frequency, and after duration (in ms.) we stop playing again static void playTone(int tone, int duration) { buzzer.period_us(1000000/tone); //period in us buzzer.write(0.10f); // 10% duty cycle, otherwise it's too loud wait_us(1000*duration/2); //play for half the length buzzer.write(0.0f); wait_us(1000*duration/2); //silence for half the length } static void play_song(std::vector<int>* melody, std::vector<int>* duration) { output.printf("play_song\n\r"); for (int i = 0; i < melody->size(); i++) { int tone = melody->at(0); // BPM is quarter notes per minute, so length in milliseconds is: int length = static_cast<int>(static_cast<float>(1000 / duration->at(0)) * (60000.0f / static_cast<float>(BPM * 1000))); // printf("tone %d, length %d, duration %d\r\n", tone, length, duration->at(0)); if (melody->at(i) != 0) { playTone(melody->at(i), length); } else { buzzer = 0.0f; wait_ms(length); } } } /* * The buzzer contains two properties (notes, duration) and a function (play). * When the function play_song_from_cloud is executed, the notes and duration patterns are read, * and the song will be played. */ class BuzzerResource { public: BuzzerResource() { // create ObjectID with metadata tag of 'buzzer', which is not defined by the LWM2M standard but we can use it for this demo buzzer_object = M2MInterfaceFactory::create_object("buzzer"); M2MObjectInstance* buzzer_inst = buzzer_object->create_object_instance(); // notes resource M2MResource* notes_res = buzzer_inst->create_dynamic_resource("notes", "", M2MResourceInstance::STRING, true); //observable // read and write notes_res->set_operation(M2MBase::GET_PUT_ALLOWED); // set initial pattern char notes_buffer[100]; int notes_size = sprintf(notes_buffer,"262:277"); notes_res->set_value((const uint8_t*)notes_buffer, (uint32_t)notes_size); // duration resource M2MResource* duration_res = buzzer_inst->create_dynamic_resource("duration", "", M2MResourceInstance::STRING, true); //observable duration_res->set_operation(M2MBase::GET_PUT_ALLOWED); // set initial pattern char dur_buffer[100]; int dur_size = sprintf(dur_buffer,"4:4"); duration_res->set_value((const uint8_t*)dur_buffer, (uint32_t)dur_size); // play resource M2MResource* play_res = buzzer_inst->create_dynamic_resource("play", "", M2MResourceInstance::STRING, false); //not observable play_res->set_operation(M2MBase::POST_ALLOWED); play_res->set_execute_function(execute_callback(this, &BuzzerResource::play_song_cloud)); } M2MObject* get_object() { return buzzer_object; } /*TODO - move the actual call to play_song_cloud to the main function, to avoid running it in interrupt context. Use a flag or semaphore set by the callback and checked for in the main function */ void play_song_cloud(void *) { output.printf("play song cloud triggered!\r\n"); // read the object storing resources 'notes' and 'duration' M2MObjectInstance* inst = buzzer_object->object_instance(); M2MResource* n_res = inst->resource("notes"); // values in mbed Client are all buffers, and we need a vector of int's uint8_t* n_buffIn = NULL; uint32_t n_sizeIn; n_res->get_value(n_buffIn, n_sizeIn); output.printf("notes = %s\n\r",n_buffIn); std::stringstream notesPattern((char*)n_buffIn, n_sizeIn); std::vector<int>* notes = new std::vector<int>; { std::string n_item; while (std::getline(notesPattern, n_item, ':')) { notes->push_back(atoi((const char*)n_item.c_str())); } } M2MResource* d_res = inst->resource("duration"); // values in mbed Client are all buffers, and we need a vector of int's uint8_t* d_buffIn = NULL; uint32_t d_sizeIn; d_res->get_value(d_buffIn, d_sizeIn); output.printf("durations = %s\n\r",d_buffIn); //TODO: investigate why passing in d_sizeIn causes it to think there are always 0 durations //std::stringstream durationPattern((char*)d_buffIn, d_sizeIn); std::stringstream durationPattern((char*)d_buffIn, 100); std::vector<int>* durations = new std::vector<int>; { std::string d_item; while (std::getline(durationPattern, d_item, ':')) { durations->push_back(atoi((const char*)d_item.c_str())); } } if (notes->size() != durations->size()) { output.printf("Notes and duration have different sizes (%d vs %d), abort!\r\n", notes->size(), durations->size()); return; } play_song(notes, durations); } private: M2MObject* buzzer_object; }; // Entry point to the program int main() { green = 1; // turn green off // This sets up the network interface configuration which will be used // by LWM2M Client API to communicate with mbed Device server. eth.init(); //Use DHCP eth.connect(); output.printf("[ETH] IP address %s\r\n", eth.getIPAddress()); output.printf("[ETH] Device name %s\r\n", MBED_ENDPOINT_NAME); // Create LWM2M Client API interface to manage register and unregister mbed_client.create_interface(); // Create resource for interactions between the device and server BuzzerResource * buzzer_resource = new BuzzerResource(); // Create LWM2M server object specifying mbed device server // information. M2MSecurity* register_object = mbed_client.create_register_object(); // Add all the objects that you would like to register // into the list and pass the list for register API. M2MObjectList object_list; object_list.push_back(buzzer_resource->get_object()); mbed_client.set_register_object(register_object); // Register with mbed Device Connector mbed_client.test_register(register_object, object_list); //TODO: should check for play command received and play song from main // to avoid doing too much in interrupt context. while (true) { wait_ms(25000); //wait 25 seconds output.printf("Updating registration\n\r"); mbed_client.test_update_register(); //update registration } }