Example showing the ublox Cellular GPS/GNSS module with the online PubNub service on an LPC4088 Experiment Base Board
Dependencies: C027_Support C12832 EALib LM75B MMA7660 PubNub mbed-rtos mbed picojson
Diff: PubNubDemo.cpp
- Revision:
- 0:e2c6c039dfbe
- Child:
- 2:5f22df5ec656
diff -r 000000000000 -r e2c6c039dfbe PubNubDemo.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PubNubDemo.cpp Sun Mar 02 01:51:30 2014 +0000 @@ -0,0 +1,161 @@ +#include <cstring> + +#include "mbed.h" +#include "EthernetInterface.h" +#include "C12832_lcd.h" +#include "MMA7660.h" +#include "LM75B.h" + +#include "picojson.h" +#include "PubNub.h" + + +/* Demo of PubNub + the mbed application board. */ + +/* How to get things set up: */ +/* 1. Tune in at the PubNub Developer Console, with the following + * keys (press Subscribe afterwards): */ +const char pubkey[] = "demo"; +const char subkey[] = "demo"; +const char channel[] = "hello_world2"; +/* 2. Attach your mbed board to your computer. A folder should pop up like + * if you plug in a USB memory stick. */ +/* 3. Open this example in the mbed web IDE and hit the Compile button. */ +/* 4. A download popup with a .bin file will appear; save it in the USB + * mbed folder. */ +/* 5. Press reset button on the mbed to start things up. */ + +/* You will see the board publish a "status" message that shows its + * current temperature and physical tilt. The board's LCD should + * print some progress messages regarding that. */ +/* You can make the board do things too, by sending messages like: + * { "send_status": true } + * { "lcd": "Hi there!" } + * { "beep": true } + * { "rgbled": {"r": 0.5, "g": 1, "b": 0} } + * Try it out! Paste these in the Message window and press the send icon. + */ + +Serial pc(USBTX, USBRX); // tx, rx +C12832_LCD lcd; // Graphics LCD +MMA7660 MMA(p28, p27); // I2C Accelerometer +LM75B tmp(p28,p27); // I2C Temperature Sensor + +PwmOut led_r(p23); // RGB LED with 3 PWM outputs for dimmer control +PwmOut led_g(p24); +PwmOut led_b(p25); +PwmOut speaker(p26); // Speaker with PWM driver + +EthernetInterface eth; +PubNub pn(pubkey, subkey); + +void status_msg(PubNub &pn) +{ + /* Read sensors. */ + float m[3]; + MMA.readData(m); + float temp = tmp.read(); + + /* Print on LCD. */ + lcd.printf("pub: mx=%.2f, my=%.2f, mz=%.2f, t=%.2f \n", m[0], m[1], m[2], temp); + + /* Prepare JSON message. */ + char jsonmsg[128]; + snprintf(jsonmsg, sizeof(jsonmsg), + "{\"status\":{\"mx\":%.2f,\"my\":%.2f,\"mz\":%.2f,\"temp\":%.2f}}", + m[0], m[1], m[2], temp); + +#if 0 + /* In some rare situations, you might want to instead use picojson + * to construct JSON messages, even though it takes a lot of memory: */ + + printf("%d: ", __LINE__); __heapstats((__heapprt)fprintf, stdout); + picojson::value msg(picojson::object_type, false); + picojson::object &msgo = msg.get<picojson::object>(); + msgo["status"] = picojson::value(picojson::object_type, false); + picojson::object &status = msgo["status"].get<picojson::object>(); + status["mx"] = picojson::value(double(mx)); + status["my"] = picojson::value(double(my)); + status["temp"] = picojson::value(temp); + strcpy(jsonmsg, msg.serialize().c_str()); + printf("%d: ", __LINE__); __heapstats((__heapprt)fprintf, stdout); +#endif + + /* Publish on PubNub. */ + PubNubRes ret = pn.publish(channel, jsonmsg); + if (ret != PNR_OK) + lcd.printf("puberr: %d \n", ret); +} + +void process_msg(PubNub &pn, const char *jsonmsg) +{ + /* Use the picojson parser since we want to deal with complex messages. + * If you are short on memory, you can find an example for parsing simple + * JSON messages in the PubNub::subscribe() API docs. */ + picojson::value msg; + std::string err = picojson::parse(msg, jsonmsg, jsonmsg + strlen(jsonmsg)); + if (!err.empty()) { + lcd.printf("JSON parse: %s \n", err.c_str()); + return; + } + + if (msg.get("send_status").get<bool>()) { + status_msg(pn); + } + if (msg.get("lcd").is<std::string>()) { + lcd.printf("in: %s \n", msg.get("lcd").get<std::string>().c_str()); + } + if (msg.get("beep").is<bool>()) { + speaker = msg.get("beep").get<bool>() ? 0.5 : 0; + } + if (msg.get("led").is<picojson::object>()) { + picojson::value led = msg.get("led"); + if (led.get("r").is<double>()) led_r = 1.0 - led.get("r").get<double>(); + if (led.get("g").is<double>()) led_g = 1.0 - led.get("g").get<double>(); + if (led.get("b").is<double>()) led_b = 1.0 - led.get("b").get<double>(); + } +} + +int main() +{ + /* For debugging, you may find it useful to print memory usage + * stats. AvailableMemory may be flaky, but the following is nice. + * It will get printed to the USB serial port interface. */ + printf("%d: ", __LINE__); __heapstats((__heapprt)fprintf, stdout); + + /* Generate a 800Hz tone using PWM hardware output */ + speaker.period(1.0/800.0); // 800hz period + led_r = led_g = led_b = 1.0; // lights out + + lcd.cls(); + lcd.locate(0,0); + + if (!MMA.testConnection()) + lcd.printf("MMA error \n"); + + eth.init(); // Use DHCP + eth.connect(); + + status_msg(pn); + // lcd.printf("pub... "); + + while (1) { + // lcd.printf("sub... "); + printf("%d: ", __LINE__); __heapstats((__heapprt)fprintf, stdout); + + char *reply = NULL; + PubNubRes ret = pn.subscribe(channel, &reply); + if (ret != PNR_OK) { + lcd.printf("suberr: %d \n", ret); + wait(1.0); + continue; + } + + if (reply) { + // lcd.printf("recv(%s)\n", reply); + process_msg(pn, reply); + } + + wait(0.5); // avoid busy loop in bad situations + } +} \ No newline at end of file