Donovan Baillieu
/
mbedmusical
Program for mbed with MQTT music
Revision 0:5e04051a59b9, committed 2018-01-08
- Comitter:
- donovanbaillieu
- Date:
- Mon Jan 08 15:02:58 2018 +0000
- Commit message:
- initial commit
Changed in this revision
diff -r 000000000000 -r 5e04051a59b9 .gitignore --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.gitignore Mon Jan 08 15:02:58 2018 +0000 @@ -0,0 +1,4 @@ +.build +.mbed +projectfiles +*.py*
diff -r 000000000000 -r 5e04051a59b9 C12832.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/C12832.lib Mon Jan 08 15:02:58 2018 +0000 @@ -0,0 +1,1 @@ +https://mbed.org/teams/components/code/C12832/#03069e3deaa4
diff -r 000000000000 -r 5e04051a59b9 Linux-example/LinuxIPStack.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Linux-example/LinuxIPStack.h Mon Jan 08 15:02:58 2018 +0000 @@ -0,0 +1,119 @@ +#if !defined(LINUX_IPSTACK_H) +#define LINUX_IPSTACK_H + +class IPStack +{ +public: + IPStack() + { + + } + + int Socket_error(const char* aString) + { + + if (errno != EINTR && errno != EAGAIN && errno != EINPROGRESS && errno != EWOULDBLOCK) + { + if (strcmp(aString, "shutdown") != 0 || (errno != ENOTCONN && errno != ECONNRESET)) + printf("Socket error %s in %s for socket %d\n", strerror(errno), aString, mysock); + } + return errno; + } + + int connect(const char* hostname, int port) + { + int type = SOCK_STREAM; + struct sockaddr_in address; + int rc = -1; + sa_family_t family = AF_INET; + struct addrinfo *result = NULL; + struct addrinfo hints = {0, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, 0, NULL, NULL, NULL}; + + if ((rc = getaddrinfo(hostname, NULL, &hints, &result)) == 0) + { + struct addrinfo* res = result; + + /* prefer ip4 addresses */ + while (res) + { + if (res->ai_family == AF_INET) + { + result = res; + break; + } + res = res->ai_next; + } + + if (result->ai_family == AF_INET) + { + address.sin_port = htons(port); + address.sin_family = family = AF_INET; + address.sin_addr = ((struct sockaddr_in*)(result->ai_addr))->sin_addr; + } + else + rc = -1; + + freeaddrinfo(result); + } + + if (rc == 0) + { + mysock = socket(family, type, 0); + if (mysock != -1) + { + int opt = 1; + + //if (setsockopt(mysock, SOL_SOCKET, SO_NOSIGPIPE, (void*)&opt, sizeof(opt)) != 0) + // printf("Could not set SO_NOSIGPIPE for socket %d", mysock); + + rc = ::connect(mysock, (struct sockaddr*)&address, sizeof(address)); + } + } + + return rc; + } + + int read(char* buffer, int len, int timeout_ms) + { + struct timeval interval = {timeout_ms / 1000, (timeout_ms % 1000) * 1000}; + if (interval.tv_sec < 0 || (interval.tv_sec == 0 && interval.tv_usec <= 0)) + { + interval.tv_sec = 0; + interval.tv_usec = 100; + } + + setsockopt(mysock, SOL_SOCKET, SO_RCVTIMEO, (char *)&interval, sizeof(struct timeval)); + + //printf("reading %d bytes\n", len); + int rc = ::recv(mysock, buffer, (size_t)len, 0); + if (rc == -1) + Socket_error("read"); + //printf("read %d bytes\n", rc); + return rc; + } + + int write(char* buffer, int len, int timeout) + { + struct timeval tv; + + tv.tv_sec = 0; /* 30 Secs Timeout */ + tv.tv_usec = timeout * 1000; // Not init'ing this can cause strange errors + + setsockopt(mysock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,sizeof(struct timeval)); + int rc = ::write(mysock, buffer, len); + //printf("write rc %d\n", rc); + return rc; + } + + int disconnect() + { + return ::close(mysock); + } + +private: + + int mysock; + +}; + +#endif \ No newline at end of file
diff -r 000000000000 -r 5e04051a59b9 Linux-example/LinuxMQTT.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Linux-example/LinuxMQTT.h Mon Jan 08 15:02:58 2018 +0000 @@ -0,0 +1,64 @@ +#if !defined(LINUXMQTT_H) +#define LINUXMQTT_H + +class Countdown +{ +public: + Countdown() + { + + } + + Countdown(int ms) + { + countdown_ms(ms); + } + + + bool expired() + { + struct timeval now, res; + gettimeofday(&now, NULL); + timersub(&end_time, &now, &res); + //printf("left %d ms\n", (res.tv_sec < 0) ? 0 : res.tv_sec * 1000 + res.tv_usec / 1000); + //if (res.tv_sec > 0 || res.tv_usec > 0) + // printf("expired %d %d\n", res.tv_sec, res.tv_usec); + return res.tv_sec < 0 || (res.tv_sec == 0 && res.tv_usec <= 0); + } + + + void countdown_ms(int ms) + { + struct timeval now; + gettimeofday(&now, NULL); + struct timeval interval = {ms / 1000, (ms % 1000) * 1000}; + //printf("interval %d %d\n", interval.tv_sec, interval.tv_usec); + timeradd(&now, &interval, &end_time); + } + + + void countdown(int seconds) + { + struct timeval now; + gettimeofday(&now, NULL); + struct timeval interval = {seconds, 0}; + timeradd(&now, &interval, &end_time); + } + + + int left_ms() + { + struct timeval now, res; + gettimeofday(&now, NULL); + timersub(&end_time, &now, &res); + //printf("left %d ms\n", (res.tv_sec < 0) ? 0 : res.tv_sec * 1000 + res.tv_usec / 1000); + return (res.tv_sec < 0) ? 0 : res.tv_sec * 1000 + res.tv_usec / 1000; + } + +private: + + struct timeval end_time; +}; + + +#endif \ No newline at end of file
diff -r 000000000000 -r 5e04051a59b9 Linux-example/linux-main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Linux-example/linux-main.cpp Mon Jan 08 15:02:58 2018 +0000 @@ -0,0 +1,149 @@ +/******************************************************************************* + * Copyright (c) 2014 IBM Corp. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Ian Craggs - initial API and implementation and/or initial documentation + *******************************************************************************/ + + /** + This is a sample program to illustrate the use of the MQTT Client library + on Linux. The Client class requires two classes which mediate + access to system interfaces for networking and timing. As long as these two + classes provide the required public programming interfaces, it does not matter + what facilities they use underneath. In this program, they use the Linux + system libraries. + + */ + +#if defined(LINUX) + +#include "LinuxMQTT.h" +#include "LinuxIPStack.h" +#include "MQTTClient.h" + +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/param.h> +#include <sys/time.h> +#include <sys/select.h> +#include <netinet/in.h> +#include <netinet/tcp.h> +#include <arpa/inet.h> +#include <netdb.h> +#include <stdio.h> +#include <unistd.h> +#include <errno.h> +#include <fcntl.h> + +#include <stdlib.h> +#include <string.h> +#include <signal.h> + +#define DEFAULT_STACK_SIZE -1 + + +int arrivedcount = 0; + +void messageArrived(MQTT::Message* message) +{ + printf("Message %d arrived: qos %d, retained %d, dup %d, packetid %d\n", + ++arrivedcount, message->qos, message->retained, message->dup, message->id); + printf("Payload %.*s\n", message->payloadlen, (char*)message->payload); +} + + +int connect(MQTT::Client<IPStack, Countdown>::connectionLostInfo* info) +{ + const char* hostname = "localhost"; //"m2m.eclipse.org"; + int port = 1883; + printf("Connecting to %s:%d\n", hostname, port); + int rc = info->network->connect(hostname, port); + if (rc != 0) + printf("rc from TCP connect is %d\n", rc); + + MQTTPacket_connectData data = MQTTPacket_connectData_initializer; + data.MQTTVersion = 3; + data.clientID.cstring = (char*)"mbed-icraggs"; + rc = info->client->connect(&data); + if (rc != 0) + printf("rc from MQTT connect is %d\n", rc); + + return rc; +} + + +int main(int argc, char* argv[]) +{ + IPStack ipstack = IPStack(); + float version = 0.3; + const char* topic = "mbed-sample"; + + printf("Version is %f\n", version); + + MQTT::Client<IPStack, Countdown> client = MQTT::Client<IPStack, Countdown>(ipstack); + + client.setConnectionLostHandler(connect); + + MQTT::Client<IPStack, Countdown>::connectionLostInfo info = {&client, &ipstack}; + int rc = connect(&info); + + rc = client.subscribe(topic, MQTT::QOS2, messageArrived); + if (rc != 0) + printf("rc from MQTT subscribe is %d\n", rc); + + MQTT::Message message; + + // QoS 0 + char buf[100]; + sprintf(buf, "Hello World! QoS 0 message from app version %f", version); + message.qos = MQTT::QOS0; + message.retained = false; + message.dup = false; + message.payload = (void*)buf; + message.payloadlen = strlen(buf)+1; + rc = client.publish(topic, &message); + while (arrivedcount == 0) + client.yield(100); + + // QoS 1 + printf("Now QoS 1\n"); + sprintf(buf, "Hello World! QoS 1 message from app version %f", version); + message.qos = MQTT::QOS1; + message.payloadlen = strlen(buf)+1; + rc = client.publish(topic, &message); + while (arrivedcount == 1) + client.yield(100); + + // QoS 2 + sprintf(buf, "Hello World! QoS 2 message from app version %f", version); + message.qos = MQTT::QOS2; + message.payloadlen = strlen(buf)+1; + rc = client.publish(topic, &message); + while (arrivedcount == 2) + client.yield(100); + + rc = client.unsubscribe(topic); + if (rc != 0) + printf("rc from unsubscribe was %d\n", rc); + + rc = client.disconnect(); + if (rc != 0) + printf("rc from disconnect was %d\n", rc); + + ipstack.disconnect(); + + printf("Finishing with %d messages received\n", arrivedcount); + + return 0; +} + +#endif
diff -r 000000000000 -r 5e04051a59b9 MQTT.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MQTT.lib Mon Jan 08 15:02:58 2018 +0000 @@ -0,0 +1,1 @@ +https://mbed.org/teams/mqtt/code/MQTT/#c37c8236e84a
diff -r 000000000000 -r 5e04051a59b9 MQTTNetwork.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MQTTNetwork.h Mon Jan 08 15:02:58 2018 +0000 @@ -0,0 +1,38 @@ +#ifndef _MQTTNETWORK_H_ +#define _MQTTNETWORK_H_ + +#include "NetworkInterface.h" + +class MQTTNetwork { +public: + MQTTNetwork(NetworkInterface* aNetwork) : network(aNetwork) { + socket = new TCPSocket(); + } + + ~MQTTNetwork() { + delete socket; + } + + int read(unsigned char* buffer, int len, int timeout) { + return socket->recv(buffer, len); + } + + int write(unsigned char* buffer, int len, int timeout) { + return socket->send(buffer, len); + } + + int connect(const char* hostname, int port) { + socket->open(network); + return socket->connect(hostname, port); + } + + int disconnect() { + return socket->close(); + } + +private: + NetworkInterface* network; + TCPSocket* socket; +}; + +#endif // _MQTTNETWORK_H_
diff -r 000000000000 -r 5e04051a59b9 README.md --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/README.md Mon Jan 08 15:02:58 2018 +0000 @@ -0,0 +1,75 @@ +# Getting started with Blinky on mbed OS + +This guide reviews the steps required to get Blinky working on an mbed OS platform. + +Please install [mbed CLI](https://github.com/ARMmbed/mbed-cli#installing-mbed-cli). + +## Import the example application + +From the command-line, import the example: + +``` +mbed import mbed-os-example-blinky +cd mbed-os-example-blinky +``` + +### Now compile + +Invoke `mbed compile`, and specify the name of your platform and your favorite toolchain (`GCC_ARM`, `ARM`, `IAR`). For example, for the ARM Compiler 5: + +``` +mbed compile -m K64F -t ARM +``` + +Your PC may take a few minutes to compile your code. At the end, you see the following result: + +``` +[snip] ++----------------------------+-------+-------+------+ +| Module | .text | .data | .bss | ++----------------------------+-------+-------+------+ +| Misc | 13939 | 24 | 1372 | +| core/hal | 16993 | 96 | 296 | +| core/rtos | 7384 | 92 | 4204 | +| features/FEATURE_IPV4 | 80 | 0 | 176 | +| frameworks/greentea-client | 1830 | 60 | 44 | +| frameworks/utest | 2392 | 512 | 292 | +| Subtotals | 42618 | 784 | 6384 | ++----------------------------+-------+-------+------+ +Allocated Heap: unknown +Allocated Stack: unknown +Total Static RAM memory (data + bss): 7168 bytes +Total RAM memory (data + bss + heap + stack): 7168 bytes +Total Flash memory (text + data + misc): 43402 bytes +Image: .\.build\K64F\ARM\mbed-os-example-blinky.bin +``` + +### Program your board + +1. Connect your mbed device to the computer over USB. +1. Copy the binary file to the mbed device. +1. Press the reset button to start the program. + +The LED on your platform turns on and off. + +## Export the project to Keil MDK, and debug your application + +From the command-line, run the following command: + +``` +mbed export -m K64F -i uvision +``` + +To debug the application: + +1. Start uVision. +1. Import the uVision project generated earlier. +1. Compile your application, and generate an `.axf` file. +1. Make sure uVision is configured to debug over CMSIS-DAP (From the Project menu > Options for Target '...' > Debug tab > Use CMSIS-DAP Debugger). +1. Set breakpoints, and start a debug session. + +![Image of uVision](img/uvision.png) + +## Troubleshooting + +If you have problems, you can review the [documentation](https://os.mbed.com/docs/latest/tutorials/debugging.html) for suggestions on what could be wrong and how to fix it.
diff -r 000000000000 -r 5e04051a59b9 easy-connect.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easy-connect.lib Mon Jan 08 15:02:58 2018 +0000 @@ -0,0 +1,1 @@ +https://github.com/ARMmbed/easy-connect/#cb933fb19cda0a733a64d6b71d271fb6bdaf9e6d
diff -r 000000000000 -r 5e04051a59b9 main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Mon Jan 08 15:02:58 2018 +0000 @@ -0,0 +1,186 @@ +/******************************************************************************* + * Copyright (c) 2014, 2015 IBM Corp. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Ian Craggs - initial API and implementation and/or initial documentation + * Ian Craggs - make sure QoS2 processing works, and add device headers + *******************************************************************************/ + + /** + This is a sample program to illustrate the use of the MQTT Client library + on the mbed platform. The Client class requires two classes which mediate + access to system interfaces for networking and timing. As long as these two + classes provide the required public programming interfaces, it does not matter + what facilities they use underneath. In this program, they use the mbed + system libraries. + + */ + + // change this to 1 to output messages to LCD instead of serial +#define USE_LCD 0 + +#if USE_LCD +#include "C12832.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sstream> +#include <iostream> +#include <string> + +// the actual pins are defined in mbed_app.json and can be overridden per target +C12832 lcd(LCD_MOSI, LCD_SCK, LCD_MISO, LCD_A0, LCD_NCS); + +#define logMessage lcd.cls();lcd.printf + +#else + +#define logMessage printf + +#endif + +#define MQTTCLIENT_QOS2 1 + +#include "easy-connect.h" +#include "MQTTNetwork.h" +#include "MQTTmbed.h" +#include "MQTTClient.h" + +PwmOut speaker(p26); + +int arrivedcount = 0; + +/* Mail */ +typedef struct { + int frequency; /* AD result of measured voltage */ +} mail_t; + +Mail<mail_t, 16> mail_box; + +void messageArrived(MQTT::MessageData& md) +{ + MQTT::Message &message = md.message; + logMessage("Message arrived: qos %d, retained %d, dup %d, packetid %d\r\n", message.qos, message.retained, message.dup, message.id); + logMessage("Payload %.*s\r\n", message.payloadlen, (char*)message.payload); + ++arrivedcount; + + mail_t *mail = mail_box.alloc(); + + int x = atoi((char*)message.payload); + mail->frequency = x; + + mail_box.put(mail); + + /*for (int i=0; i<10; i++) { + speaker.period(1.0/x); // 500hz period + speaker =0.25; //25% duty cycle - mid range volume + wait(.02); + speaker=0.0; // turn off audio + wait(0.5); + }*/ +} + +void threadmusic() { + while (true) { + osEvent evt = mail_box.get(); + if (evt.status == osEventMail) { + mail_t *mail = (mail_t*)evt.value.p; + speaker.period(1.0/mail->frequency); + speaker =0.5; + wait(0.5); + speaker=0.0; + wait(0.5); + mail_box.free(mail); + } + } + } + +Thread thread(threadmusic); + +int main(int argc, char* argv[]) +{ + float version = 0.6; + char* topic = "music"; + + logMessage("HelloMQTT: version is %.2f\r\n", version); + + NetworkInterface* network = easy_connect(true); + if (!network) { + return -1; + } + + MQTTNetwork mqttNetwork(network); + + MQTT::Client<MQTTNetwork, Countdown> client(mqttNetwork); + + const char* hostname = "10.0.0.133"; + int port = 1883; + logMessage("Connecting to %s:%d\r\n", hostname, port); + int rc = mqttNetwork.connect(hostname, port); + if (rc != 0) + logMessage("rc from TCP connect is %d\r\n", rc); + + MQTTPacket_connectData data = MQTTPacket_connectData_initializer; + data.MQTTVersion = 3; + data.clientID.cstring = "mbedmusic"; + data.username.cstring = "testuser"; + data.password.cstring = "testpassword"; + if ((rc = client.connect(data)) != 0) + logMessage("rc from MQTT connect is %d\r\n", rc); + + if ((rc = client.subscribe(topic, MQTT::QOS2, messageArrived)) != 0) + logMessage("rc from MQTT subscribe is %d\r\n", rc); + + /*// QoS 0 + char buf[100]; + sprintf(buf, "Hello World! QoS 0 message from app version %f\r\n", version); + message.qos = MQTT::QOS0; + message.retained = false; + message.dup = false; + message.payload = (void*)buf; + message.payloadlen = strlen(buf)+1; + rc = client.publish(topic, message); + while (arrivedcount < 1) + client.yield(100); + + // QoS 1 + sprintf(buf, "Hello World! QoS 1 message from app version %f\r\n", version); + message.qos = MQTT::QOS1; + message.payloadlen = strlen(buf)+1; + rc = client.publish(topic, message); + while (arrivedcount < 2) + client.yield(100); + + // QoS 2 + sprintf(buf, "Hello World! QoS 2 message from app version %f\r\n", version); + message.qos = MQTT::QOS2; + message.payloadlen = strlen(buf)+1; + rc = client.publish(topic, message); + while (arrivedcount < 3) + client.yield(100); + + if ((rc = client.unsubscribe(topic)) != 0) + logMessage("rc from unsubscribe was %d\r\n", rc); + + if ((rc = client.disconnect()) != 0) + logMessage("rc from disconnect was %d\r\n", rc); + + mqttNetwork.disconnect(); + + logMessage("Version %.2f: finish %d msgs\r\n", version, arrivedcount);*/ + + while (true){ + client.yield(700); + } + + return 0; +}
diff -r 000000000000 -r 5e04051a59b9 mbed-os.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed-os.lib Mon Jan 08 15:02:58 2018 +0000 @@ -0,0 +1,1 @@ +https://github.com/ARMmbed/mbed-os/#eca67ca7dafab4ef70c21e2463b541132d0dd691
diff -r 000000000000 -r 5e04051a59b9 mbed_app.json --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed_app.json Mon Jan 08 15:02:58 2018 +0000 @@ -0,0 +1,69 @@ +{ + "config": { + "network-interface":{ + "help": "options are ETHERNET, WIFI_ESP8266, WIFI_ODIN, WIFI_RTW, MESH_LOWPAN_ND, MESH_THREAD, CELLULAR_ONBOARD", + "value": "ETHERNET" + }, + "mesh_radio_type": { + "help": "options are ATMEL, MCR20", + "value": "ATMEL" + }, + "esp8266-tx": { + "help": "Pin used as TX (connects to ESP8266 RX)", + "value": "D1" + }, + "esp8266-rx": { + "help": "Pin used as RX (connects to ESP8266 TX)", + "value": "D0" + }, + "esp8266-ssid": { + "value": "\"SSID\"" + }, + "esp8266-password": { + "value": "\"Password\"" + }, + "esp8266-debug": { + "value": true + }, + "lcd-mosi": { + "value": "D11", + "macro_name": "LCD_MOSI" + }, + "lcd-sck": { + "value": "D13", + "macro_name": "LCD_SCK" + }, + "lcd-miso": { + "value": "D12", + "macro_name": "LCD_MISO" + }, + "lcd-a0": { + "value": "D7", + "macro_name": "LCD_A0" + }, + "lcd-ncs": { + "value": "D10", + "macro_name": "LCD_NCS" + } + }, + "target_overrides": { + "*": { + "target.features_add": ["NANOSTACK", "LOWPAN_ROUTER", "COMMON_PAL"], + "mbed-mesh-api.6lowpan-nd-channel-page": 0, + "mbed-mesh-api.6lowpan-nd-channel": 12, + "mbed-trace.enable": 0 + }, + "HEXIWEAR": { + "esp8266-tx": "PTD3", + "esp8266-rx": "PTD2" + }, + "NUCLEO_F401RE": { + "esp8266-tx": "D8", + "esp8266-rx": "D2" + }, + "NUCLEO_F411RE": { + "esp8266-tx": "D8", + "esp8266-rx": "D2" + } + } +}