Connect to the internet and play songs from a web app

Dependencies:   mbed Socket lwip-eth lwip-sys lwip

Committer:
maclobdell
Date:
Wed May 18 19:06:32 2016 +0000
Revision:
0:f7c60d3e7b8a
clean version

Who changed what in which revision?

UserRevisionLine numberNew contents of line
maclobdell 0:f7c60d3e7b8a 1 /*
maclobdell 0:f7c60d3e7b8a 2 * Copyright (c) 2015 ARM Limited. All rights reserved.
maclobdell 0:f7c60d3e7b8a 3 * SPDX-License-Identifier: Apache-2.0
maclobdell 0:f7c60d3e7b8a 4 * Licensed under the Apache License, Version 2.0 (the License); you may
maclobdell 0:f7c60d3e7b8a 5 * not use this file except in compliance with the License.
maclobdell 0:f7c60d3e7b8a 6 * You may obtain a copy of the License at
maclobdell 0:f7c60d3e7b8a 7 *
maclobdell 0:f7c60d3e7b8a 8 * http://www.apache.org/licenses/LICENSE-2.0
maclobdell 0:f7c60d3e7b8a 9 *
maclobdell 0:f7c60d3e7b8a 10 * Unless required by applicable law or agreed to in writing, software
maclobdell 0:f7c60d3e7b8a 11 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
maclobdell 0:f7c60d3e7b8a 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
maclobdell 0:f7c60d3e7b8a 13 * See the License for the specific language governing permissions and
maclobdell 0:f7c60d3e7b8a 14 * limitations under the License.
maclobdell 0:f7c60d3e7b8a 15 */
maclobdell 0:f7c60d3e7b8a 16
maclobdell 0:f7c60d3e7b8a 17 #include "mbed.h" // this tells us to load mbed OS related functions
maclobdell 0:f7c60d3e7b8a 18 #include "tones.h" // list of all the tones and their frequencies
maclobdell 0:f7c60d3e7b8a 19 #include "simpleclient.h"
maclobdell 0:f7c60d3e7b8a 20 #include <string>
maclobdell 0:f7c60d3e7b8a 21 #include <sstream>
maclobdell 0:f7c60d3e7b8a 22 #include <vector>
maclobdell 0:f7c60d3e7b8a 23
maclobdell 0:f7c60d3e7b8a 24 Serial output(USBTX, USBRX);
maclobdell 0:f7c60d3e7b8a 25
maclobdell 0:f7c60d3e7b8a 26 PwmOut buzzer(D3); // our buzzer is a PWM output (pulse-width modulation)
maclobdell 0:f7c60d3e7b8a 27
maclobdell 0:f7c60d3e7b8a 28 static int BPM = 35;
maclobdell 0:f7c60d3e7b8a 29
maclobdell 0:f7c60d3e7b8a 30 EthernetInterface eth;
maclobdell 0:f7c60d3e7b8a 31
maclobdell 0:f7c60d3e7b8a 32 // These are example resource values for the Device Object
maclobdell 0:f7c60d3e7b8a 33 struct MbedClientDevice device = {
maclobdell 0:f7c60d3e7b8a 34 "Manufacturer_String", // Manufacturer
maclobdell 0:f7c60d3e7b8a 35 "Type_String", // Type
maclobdell 0:f7c60d3e7b8a 36 "ModelNumber_String", // ModelNumber
maclobdell 0:f7c60d3e7b8a 37 "SerialNumber_String" // SerialNumber
maclobdell 0:f7c60d3e7b8a 38 };
maclobdell 0:f7c60d3e7b8a 39
maclobdell 0:f7c60d3e7b8a 40 // Instantiate the class which implements LWM2M Client API (from simpleclient.h)
maclobdell 0:f7c60d3e7b8a 41 MbedClient mbed_client(device);
maclobdell 0:f7c60d3e7b8a 42
maclobdell 0:f7c60d3e7b8a 43 // this is our function that plays a tone.
maclobdell 0:f7c60d3e7b8a 44 // Takes in a tone frequency, and after duration (in ms.) we stop playing again
maclobdell 0:f7c60d3e7b8a 45 static void playTone(int tone, int duration) {
maclobdell 0:f7c60d3e7b8a 46
maclobdell 0:f7c60d3e7b8a 47 buzzer.period_us(1000000/tone); //period in us
maclobdell 0:f7c60d3e7b8a 48 buzzer.write(0.10f); // 10% duty cycle, otherwise it's too loud
maclobdell 0:f7c60d3e7b8a 49 wait_us(1000*duration/2); //play for half the length
maclobdell 0:f7c60d3e7b8a 50 buzzer.write(0.0f);
maclobdell 0:f7c60d3e7b8a 51 wait_us(1000*duration/2); //silence for half the length
maclobdell 0:f7c60d3e7b8a 52
maclobdell 0:f7c60d3e7b8a 53 }
maclobdell 0:f7c60d3e7b8a 54
maclobdell 0:f7c60d3e7b8a 55 static void play_song(std::vector<int>* melody, std::vector<int>* duration) {
maclobdell 0:f7c60d3e7b8a 56
maclobdell 0:f7c60d3e7b8a 57 output.printf("play_song\n\r");
maclobdell 0:f7c60d3e7b8a 58 for (int i = 0; i < melody->size(); i++) {
maclobdell 0:f7c60d3e7b8a 59 int tone = melody->at(0);
maclobdell 0:f7c60d3e7b8a 60 // BPM is quarter notes per minute, so length in milliseconds is:
maclobdell 0:f7c60d3e7b8a 61 int length = static_cast<int>(static_cast<float>(1000 / duration->at(0)) * (60000.0f / static_cast<float>(BPM * 1000)));
maclobdell 0:f7c60d3e7b8a 62
maclobdell 0:f7c60d3e7b8a 63 // printf("tone %d, length %d, duration %d\r\n", tone, length, duration->at(0));
maclobdell 0:f7c60d3e7b8a 64
maclobdell 0:f7c60d3e7b8a 65 if (melody->at(i) != 0) {
maclobdell 0:f7c60d3e7b8a 66 playTone(melody->at(i), length);
maclobdell 0:f7c60d3e7b8a 67 }
maclobdell 0:f7c60d3e7b8a 68 else {
maclobdell 0:f7c60d3e7b8a 69 buzzer = 0.0f;
maclobdell 0:f7c60d3e7b8a 70 wait_ms(length);
maclobdell 0:f7c60d3e7b8a 71 }
maclobdell 0:f7c60d3e7b8a 72 }
maclobdell 0:f7c60d3e7b8a 73 }
maclobdell 0:f7c60d3e7b8a 74
maclobdell 0:f7c60d3e7b8a 75
maclobdell 0:f7c60d3e7b8a 76 /*
maclobdell 0:f7c60d3e7b8a 77 * The buzzer contains two properties (notes, duration) and a function (play).
maclobdell 0:f7c60d3e7b8a 78 * When the function play_song_from_cloud is executed, the notes and duration patterns are read,
maclobdell 0:f7c60d3e7b8a 79 * and the song will be played.
maclobdell 0:f7c60d3e7b8a 80 */
maclobdell 0:f7c60d3e7b8a 81 class BuzzerResource {
maclobdell 0:f7c60d3e7b8a 82 public:
maclobdell 0:f7c60d3e7b8a 83 BuzzerResource() {
maclobdell 0:f7c60d3e7b8a 84 // create ObjectID with metadata tag of 'buzzer', which is not defined by the LWM2M standard but we can use it for this demo
maclobdell 0:f7c60d3e7b8a 85 buzzer_object = M2MInterfaceFactory::create_object("buzzer");
maclobdell 0:f7c60d3e7b8a 86 M2MObjectInstance* buzzer_inst = buzzer_object->create_object_instance();
maclobdell 0:f7c60d3e7b8a 87
maclobdell 0:f7c60d3e7b8a 88 // notes resource
maclobdell 0:f7c60d3e7b8a 89 M2MResource* notes_res = buzzer_inst->create_dynamic_resource("notes", "",
maclobdell 0:f7c60d3e7b8a 90 M2MResourceInstance::STRING, true); //observable
maclobdell 0:f7c60d3e7b8a 91
maclobdell 0:f7c60d3e7b8a 92 // read and write
maclobdell 0:f7c60d3e7b8a 93 notes_res->set_operation(M2MBase::GET_PUT_ALLOWED);
maclobdell 0:f7c60d3e7b8a 94
maclobdell 0:f7c60d3e7b8a 95 // set initial pattern
maclobdell 0:f7c60d3e7b8a 96 char notes_buffer[100];
maclobdell 0:f7c60d3e7b8a 97 int notes_size = sprintf(notes_buffer,"262:277");
maclobdell 0:f7c60d3e7b8a 98
maclobdell 0:f7c60d3e7b8a 99 notes_res->set_value((const uint8_t*)notes_buffer,
maclobdell 0:f7c60d3e7b8a 100 (uint32_t)notes_size);
maclobdell 0:f7c60d3e7b8a 101
maclobdell 0:f7c60d3e7b8a 102 // duration resource
maclobdell 0:f7c60d3e7b8a 103 M2MResource* duration_res = buzzer_inst->create_dynamic_resource("duration", "",
maclobdell 0:f7c60d3e7b8a 104 M2MResourceInstance::STRING, true); //observable
maclobdell 0:f7c60d3e7b8a 105
maclobdell 0:f7c60d3e7b8a 106 duration_res->set_operation(M2MBase::GET_PUT_ALLOWED);
maclobdell 0:f7c60d3e7b8a 107
maclobdell 0:f7c60d3e7b8a 108 // set initial pattern
maclobdell 0:f7c60d3e7b8a 109 char dur_buffer[100];
maclobdell 0:f7c60d3e7b8a 110 int dur_size = sprintf(dur_buffer,"4:4");
maclobdell 0:f7c60d3e7b8a 111
maclobdell 0:f7c60d3e7b8a 112 duration_res->set_value((const uint8_t*)dur_buffer,
maclobdell 0:f7c60d3e7b8a 113 (uint32_t)dur_size);
maclobdell 0:f7c60d3e7b8a 114
maclobdell 0:f7c60d3e7b8a 115 // play resource
maclobdell 0:f7c60d3e7b8a 116 M2MResource* play_res = buzzer_inst->create_dynamic_resource("play", "",
maclobdell 0:f7c60d3e7b8a 117 M2MResourceInstance::STRING, false); //not observable
maclobdell 0:f7c60d3e7b8a 118
maclobdell 0:f7c60d3e7b8a 119 play_res->set_operation(M2MBase::POST_ALLOWED);
maclobdell 0:f7c60d3e7b8a 120
maclobdell 0:f7c60d3e7b8a 121 play_res->set_execute_function(execute_callback(this, &BuzzerResource::play_song_cloud));
maclobdell 0:f7c60d3e7b8a 122
maclobdell 0:f7c60d3e7b8a 123
maclobdell 0:f7c60d3e7b8a 124 }
maclobdell 0:f7c60d3e7b8a 125
maclobdell 0:f7c60d3e7b8a 126 M2MObject* get_object() {
maclobdell 0:f7c60d3e7b8a 127 return buzzer_object;
maclobdell 0:f7c60d3e7b8a 128 }
maclobdell 0:f7c60d3e7b8a 129
maclobdell 0:f7c60d3e7b8a 130 /*TODO - move the actual call to play_song_cloud to the main function, to avoid
maclobdell 0:f7c60d3e7b8a 131 running it in interrupt context. Use a flag or semaphore set by the callback and checked for
maclobdell 0:f7c60d3e7b8a 132 in the main function */
maclobdell 0:f7c60d3e7b8a 133
maclobdell 0:f7c60d3e7b8a 134 void play_song_cloud(void *) {
maclobdell 0:f7c60d3e7b8a 135
maclobdell 0:f7c60d3e7b8a 136 output.printf("play song cloud triggered!\r\n");
maclobdell 0:f7c60d3e7b8a 137
maclobdell 0:f7c60d3e7b8a 138 // read the object storing resources 'notes' and 'duration'
maclobdell 0:f7c60d3e7b8a 139 M2MObjectInstance* inst = buzzer_object->object_instance();
maclobdell 0:f7c60d3e7b8a 140
maclobdell 0:f7c60d3e7b8a 141 M2MResource* n_res = inst->resource("notes");
maclobdell 0:f7c60d3e7b8a 142
maclobdell 0:f7c60d3e7b8a 143 // values in mbed Client are all buffers, and we need a vector of int's
maclobdell 0:f7c60d3e7b8a 144 uint8_t* n_buffIn = NULL;
maclobdell 0:f7c60d3e7b8a 145 uint32_t n_sizeIn;
maclobdell 0:f7c60d3e7b8a 146 n_res->get_value(n_buffIn, n_sizeIn);
maclobdell 0:f7c60d3e7b8a 147
maclobdell 0:f7c60d3e7b8a 148 output.printf("notes = %s\n\r",n_buffIn);
maclobdell 0:f7c60d3e7b8a 149
maclobdell 0:f7c60d3e7b8a 150 std::stringstream notesPattern((char*)n_buffIn, n_sizeIn);
maclobdell 0:f7c60d3e7b8a 151
maclobdell 0:f7c60d3e7b8a 152 std::vector<int>* notes = new std::vector<int>;
maclobdell 0:f7c60d3e7b8a 153 {
maclobdell 0:f7c60d3e7b8a 154 std::string n_item;
maclobdell 0:f7c60d3e7b8a 155 while (std::getline(notesPattern, n_item, ':')) {
maclobdell 0:f7c60d3e7b8a 156 notes->push_back(atoi((const char*)n_item.c_str()));
maclobdell 0:f7c60d3e7b8a 157 }
maclobdell 0:f7c60d3e7b8a 158 }
maclobdell 0:f7c60d3e7b8a 159
maclobdell 0:f7c60d3e7b8a 160 M2MResource* d_res = inst->resource("duration");
maclobdell 0:f7c60d3e7b8a 161
maclobdell 0:f7c60d3e7b8a 162 // values in mbed Client are all buffers, and we need a vector of int's
maclobdell 0:f7c60d3e7b8a 163 uint8_t* d_buffIn = NULL;
maclobdell 0:f7c60d3e7b8a 164 uint32_t d_sizeIn;
maclobdell 0:f7c60d3e7b8a 165
maclobdell 0:f7c60d3e7b8a 166 d_res->get_value(d_buffIn, d_sizeIn);
maclobdell 0:f7c60d3e7b8a 167
maclobdell 0:f7c60d3e7b8a 168 output.printf("durations = %s\n\r",d_buffIn);
maclobdell 0:f7c60d3e7b8a 169
maclobdell 0:f7c60d3e7b8a 170 //TODO: investigate why passing in d_sizeIn causes it to think there are always 0 durations
maclobdell 0:f7c60d3e7b8a 171 //std::stringstream durationPattern((char*)d_buffIn, d_sizeIn);
maclobdell 0:f7c60d3e7b8a 172 std::stringstream durationPattern((char*)d_buffIn, 100);
maclobdell 0:f7c60d3e7b8a 173
maclobdell 0:f7c60d3e7b8a 174 std::vector<int>* durations = new std::vector<int>;
maclobdell 0:f7c60d3e7b8a 175 {
maclobdell 0:f7c60d3e7b8a 176 std::string d_item;
maclobdell 0:f7c60d3e7b8a 177 while (std::getline(durationPattern, d_item, ':')) {
maclobdell 0:f7c60d3e7b8a 178 durations->push_back(atoi((const char*)d_item.c_str()));
maclobdell 0:f7c60d3e7b8a 179 }
maclobdell 0:f7c60d3e7b8a 180 }
maclobdell 0:f7c60d3e7b8a 181
maclobdell 0:f7c60d3e7b8a 182 if (notes->size() != durations->size()) {
maclobdell 0:f7c60d3e7b8a 183 output.printf("Notes and duration have different sizes (%d vs %d), abort!\r\n", notes->size(), durations->size());
maclobdell 0:f7c60d3e7b8a 184 return;
maclobdell 0:f7c60d3e7b8a 185 }
maclobdell 0:f7c60d3e7b8a 186
maclobdell 0:f7c60d3e7b8a 187 play_song(notes, durations);
maclobdell 0:f7c60d3e7b8a 188 }
maclobdell 0:f7c60d3e7b8a 189
maclobdell 0:f7c60d3e7b8a 190 private:
maclobdell 0:f7c60d3e7b8a 191 M2MObject* buzzer_object;
maclobdell 0:f7c60d3e7b8a 192
maclobdell 0:f7c60d3e7b8a 193
maclobdell 0:f7c60d3e7b8a 194 };
maclobdell 0:f7c60d3e7b8a 195
maclobdell 0:f7c60d3e7b8a 196 // Entry point to the program
maclobdell 0:f7c60d3e7b8a 197 int main() {
maclobdell 0:f7c60d3e7b8a 198
maclobdell 0:f7c60d3e7b8a 199 green = 1; // turn green off
maclobdell 0:f7c60d3e7b8a 200
maclobdell 0:f7c60d3e7b8a 201 // This sets up the network interface configuration which will be used
maclobdell 0:f7c60d3e7b8a 202 // by LWM2M Client API to communicate with mbed Device server.
maclobdell 0:f7c60d3e7b8a 203 eth.init(); //Use DHCP
maclobdell 0:f7c60d3e7b8a 204 eth.connect();
maclobdell 0:f7c60d3e7b8a 205
maclobdell 0:f7c60d3e7b8a 206 output.printf("[ETH] IP address %s\r\n", eth.getIPAddress());
maclobdell 0:f7c60d3e7b8a 207 output.printf("[ETH] Device name %s\r\n", MBED_ENDPOINT_NAME);
maclobdell 0:f7c60d3e7b8a 208
maclobdell 0:f7c60d3e7b8a 209 // Create LWM2M Client API interface to manage register and unregister
maclobdell 0:f7c60d3e7b8a 210 mbed_client.create_interface();
maclobdell 0:f7c60d3e7b8a 211
maclobdell 0:f7c60d3e7b8a 212 // Create resource for interactions between the device and server
maclobdell 0:f7c60d3e7b8a 213 BuzzerResource * buzzer_resource = new BuzzerResource();
maclobdell 0:f7c60d3e7b8a 214
maclobdell 0:f7c60d3e7b8a 215 // Create LWM2M server object specifying mbed device server
maclobdell 0:f7c60d3e7b8a 216 // information.
maclobdell 0:f7c60d3e7b8a 217 M2MSecurity* register_object = mbed_client.create_register_object();
maclobdell 0:f7c60d3e7b8a 218
maclobdell 0:f7c60d3e7b8a 219 // Add all the objects that you would like to register
maclobdell 0:f7c60d3e7b8a 220 // into the list and pass the list for register API.
maclobdell 0:f7c60d3e7b8a 221 M2MObjectList object_list;
maclobdell 0:f7c60d3e7b8a 222 object_list.push_back(buzzer_resource->get_object());
maclobdell 0:f7c60d3e7b8a 223
maclobdell 0:f7c60d3e7b8a 224 mbed_client.set_register_object(register_object);
maclobdell 0:f7c60d3e7b8a 225
maclobdell 0:f7c60d3e7b8a 226 // Register with mbed Device Connector
maclobdell 0:f7c60d3e7b8a 227 mbed_client.test_register(register_object, object_list);
maclobdell 0:f7c60d3e7b8a 228
maclobdell 0:f7c60d3e7b8a 229 //TODO: should check for play command received and play song from main
maclobdell 0:f7c60d3e7b8a 230 // to avoid doing too much in interrupt context.
maclobdell 0:f7c60d3e7b8a 231
maclobdell 0:f7c60d3e7b8a 232 while (true) {
maclobdell 0:f7c60d3e7b8a 233
maclobdell 0:f7c60d3e7b8a 234 wait_ms(25000); //wait 25 seconds
maclobdell 0:f7c60d3e7b8a 235 output.printf("Updating registration\n\r");
maclobdell 0:f7c60d3e7b8a 236 mbed_client.test_update_register(); //update registration
maclobdell 0:f7c60d3e7b8a 237
maclobdell 0:f7c60d3e7b8a 238 }
maclobdell 0:f7c60d3e7b8a 239
maclobdell 0:f7c60d3e7b8a 240 }
maclobdell 0:f7c60d3e7b8a 241