This is a fork due to permission issues
Dependencies: mbed Socket lwip-eth lwip-sys lwip
Fork of 6_songs-from-the-cloud by
Diff: main.cpp
- Revision:
- 0:f7c60d3e7b8a
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Wed May 18 19:06:32 2016 +0000 @@ -0,0 +1,241 @@ +/* + * 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 + + } + + } +