From 2c67bb8a75d262a1616a0241629b0946c47a83c4 Mon Sep 17 00:00:00 2001 From: "Frederic.Pillon" <frederic.pillon@st.com> Date: Wed, 7 Mar 2018 09:44:19 +0100 Subject: [PATCH 1/5] Add .gitignore Signed-off-by: Frederic.Pillon <frederic.pillon@st.com> --- .gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1377554 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.swp From 96bea4c78265f9e4e6da106c22f3fa0fc4af1ece Mon Sep 17 00:00:00 2001 From: "Frederic.Pillon" <frederic.pillon@st.com> Date: Wed, 7 Mar 2018 09:45:16 +0100 Subject: [PATCH 2/5] Clean trailing space Signed-off-by: Frederic.Pillon <frederic.pillon@st.com> --- .../BTLE_sensors_TimeOfFlight_demo.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/STM32L475VG-DISCOVERY-IOT/BTLE_sensors_TimeOfFlight_demo/BTLE_sensors_TimeOfFlight_demo.ino b/examples/STM32L475VG-DISCOVERY-IOT/BTLE_sensors_TimeOfFlight_demo/BTLE_sensors_TimeOfFlight_demo.ino index 11ab5ee..721abe1 100644 --- a/examples/STM32L475VG-DISCOVERY-IOT/BTLE_sensors_TimeOfFlight_demo/BTLE_sensors_TimeOfFlight_demo.ino +++ b/examples/STM32L475VG-DISCOVERY-IOT/BTLE_sensors_TimeOfFlight_demo/BTLE_sensors_TimeOfFlight_demo.ino @@ -122,7 +122,7 @@ boolean swipe_detected() { int gesture_code; int status; boolean ret = false; - + sensor_vl53l0x->StartMeasurement(); int top_done = 0; @@ -339,7 +339,7 @@ void setup() { /* Configure the User Button in GPIO Mode */ pinMode(USER_BTN, INPUT); - + // Initialize I2C bus. dev_i2c = new TwoWire(I2C2_SDA, I2C2_SCL); dev_i2c->begin(); From 2a1dcb5168f92bf8a85172d8876bdaff9335a33e Mon Sep 17 00:00:00 2001 From: Frederic Pillon <frederic.pillon@st.com> Date: Tue, 6 Mar 2018 23:32:57 +0100 Subject: [PATCH 3/5] Added Paho MQTT C client Signed-off-by: Frederic Pillon <frederic.pillon@st.com> --- .../MQTT/MQTTClient/Hello/Hello.ino | 158 ++++++++++++++++++ .../Communication/MQTT/MQTTClient/README.md | 25 +++ 2 files changed, 183 insertions(+) create mode 100644 examples/Communication/MQTT/MQTTClient/Hello/Hello.ino create mode 100644 examples/Communication/MQTT/MQTTClient/README.md diff --git a/examples/Communication/MQTT/MQTTClient/Hello/Hello.ino b/examples/Communication/MQTT/MQTTClient/Hello/Hello.ino new file mode 100644 index 0000000..1aa3a70 --- /dev/null +++ b/examples/Communication/MQTT/MQTTClient/Hello/Hello.ino @@ -0,0 +1,158 @@ +/******************************************************************************* + * 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 contribution + * Benjamin Cabe - adapt to IPStack, and add Yun instructions + * Ian Craggs - remove sprintfs to reduce sketch size + * + * Modified by Frederic Pillon to use the STM32 Ethernet Library + * Only includes have changed: + * #include <SPI.h> + * #include <Ethernet.h> + * Replaced by: + * #include <LwIP.h> + * #include <STM32Ethernet.h> + *******************************************************************************/ + +#define WARN Serial.println + +#define MQTTCLIENT_QOS2 1 + + +#include <LwIP.h> +#include <STM32Ethernet.h> +#include <IPStack.h> +#include <Countdown.h> +#include <MQTTClient.h> + +int arrivedcount = 0; + +void messageArrived(MQTT::MessageData& md) +{ + MQTT::Message &message = md.message; + + Serial.print("Message "); + Serial.print(++arrivedcount); + Serial.print(" arrived: qos "); + Serial.print(message.qos); + Serial.print(", retained "); + Serial.print(message.retained); + Serial.print(", dup "); + Serial.print(message.dup); + Serial.print(", packetid "); + Serial.println(message.id); + Serial.print("Payload "); + Serial.println((char*)message.payload); +} + + +EthernetClient c; // replace by a YunClient if running on a Yun +IPStack ipstack(c); +MQTT::Client<IPStack, Countdown, 50, 1> client = MQTT::Client<IPStack, Countdown, 50, 1>(ipstack); + +byte mac[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 }; // replace with your device's MAC +const char* topic = "arduino-sample"; + +void connect() +{ + char hostname[] = "iot.eclipse.org"; + int port = 1883; + + Serial.print("Connecting to "); + Serial.print(hostname); + Serial.print(":"); + Serial.println(port); + + int rc = ipstack.connect(hostname, port); + if (rc != 1) + { + Serial.print("rc from TCP connect is "); + Serial.println(rc); + } + + Serial.println("MQTT connecting"); + MQTTPacket_connectData data = MQTTPacket_connectData_initializer; + data.MQTTVersion = 3; + data.clientID.cstring = (char*)"arduino-sample"; + rc = client.connect(data); + if (rc != 0) + { + Serial.print("rc from MQTT connect is "); + Serial.println(rc); + } + Serial.println("MQTT connected"); + + rc = client.subscribe(topic, MQTT::QOS2, messageArrived); + if (rc != 0) + { + Serial.print("rc from MQTT subscribe is "); + Serial.println(rc); + } + Serial.println("MQTT subscribed"); +} + +void setup() +{ + Serial.begin(9600); + Ethernet.begin(mac); + Serial.println("MQTT Hello example"); + connect(); +} + +MQTT::Message message; + +void loop() +{ + if (!client.isConnected()) + connect(); + + arrivedcount = 0; + + // Send and receive QoS 0 message + char buf[100]; + strcpy(buf, "Hello World! QoS 0 message"); + message.qos = MQTT::QOS0; + message.retained = false; + message.dup = false; + message.payload = (void*)buf; + message.payloadlen = strlen(buf)+1; + int rc = client.publish(topic, message); + while (arrivedcount == 0) + { + Serial.println("Waiting for QoS 0 message"); + client.yield(1000); + } + + // Send and receive QoS 1 message + strcpy(buf, "Hello World! QoS 1 message"); + message.qos = MQTT::QOS1; + message.payloadlen = strlen(buf)+1; + rc = client.publish(topic, message); + while (arrivedcount == 1) + { + Serial.println("Waiting for QoS 1 message"); + client.yield(1000); + } + + // Send and receive QoS 2 message + strcpy(buf, "Hello World! QoS 2 message"); + message.qos = MQTT::QOS2; + message.payloadlen = strlen(buf)+1; + rc = client.publish(topic, message); + while (arrivedcount == 2) + { + Serial.println("Waiting for QoS 2 message"); + client.yield(1000); + } + delay(2000); +} diff --git a/examples/Communication/MQTT/MQTTClient/README.md b/examples/Communication/MQTT/MQTTClient/README.md new file mode 100644 index 0000000..ad844b2 --- /dev/null +++ b/examples/Communication/MQTT/MQTTClient/README.md @@ -0,0 +1,25 @@ +# Paho MQTT C client + +Required to install prebuilt Arduino port of MQTTClient. + +See http://www.eclipse.org/paho/clients/c/embedded/ + +Download the prebuilt Arduino port of MQTTClient and in the Arduino IDE use +**_Sketch -> Include Library -> Add .ZIP Library..._** with the downloaded client zip file. + +# Examples + +## Hello +This is the basic example provided with the MQTTClient library. +It has been modified to use the [STM32 Ethernet](https://github.com/stm32duino/STM32Ethernet) library. + +Only includes have changed: +``` +#include <SPI.h> +#include <Ethernet.h> +``` +Replaced by: +``` +#include <LwIP.h> +#include <STM32Ethernet.h> +``` \ No newline at end of file From 183bd5482225d4cfaba68c44f428313e407defae Mon Sep 17 00:00:00 2001 From: "Frederic.Pillon" <frederic.pillon@st.com> Date: Wed, 7 Mar 2018 11:29:10 +0100 Subject: [PATCH 4/5] Added examples using PubSubClient (Arduino Client for MQTT) Signed-off-by: Frederic Pillon <frederic.pillon@st.com> --- .../Communication/MQTT/PubSubClient/README.md | 24 +++ .../mqtt_B-L475E-IOT01A.ino | 141 +++++++++++++ .../mqtt_STM32Ethernet/mqtt_STM32Ethernet.ino | 100 +++++++++ .../Ethernet_MQTT_Adafruit.io.ino | 160 +++++++++++++++ .../Ethernet_MQTT_Adafruit.io/README.md | 39 ++++ .../WiFi_MQTT_Adafruit.io/README.md | 35 ++++ .../WiFi_MQTT_Adafruit.io.ino | 193 ++++++++++++++++++ img/dashboard_adafruit.png | Bin 0 -> 30115 bytes 8 files changed, 692 insertions(+) create mode 100644 examples/Communication/MQTT/PubSubClient/README.md create mode 100644 examples/Communication/MQTT/PubSubClient/mqtt_B-L475E-IOT01A/mqtt_B-L475E-IOT01A.ino create mode 100644 examples/Communication/MQTT/PubSubClient/mqtt_STM32Ethernet/mqtt_STM32Ethernet.ino create mode 100644 examples/STM32F746NG-DISCOVERY/Ethernet_MQTT_Adafruit.io/Ethernet_MQTT_Adafruit.io.ino create mode 100644 examples/STM32F746NG-DISCOVERY/Ethernet_MQTT_Adafruit.io/README.md create mode 100644 examples/STM32L475VG-DISCOVERY-IOT/WiFi_MQTT_Adafruit.io/README.md create mode 100644 examples/STM32L475VG-DISCOVERY-IOT/WiFi_MQTT_Adafruit.io/WiFi_MQTT_Adafruit.io.ino create mode 100644 img/dashboard_adafruit.png diff --git a/examples/Communication/MQTT/PubSubClient/README.md b/examples/Communication/MQTT/PubSubClient/README.md new file mode 100644 index 0000000..177d2fb --- /dev/null +++ b/examples/Communication/MQTT/PubSubClient/README.md @@ -0,0 +1,24 @@ +# PubSubClient + +This library provides a client for doing simple publish/subscribe messaging with a server that supports MQTT. + +https://github.com/knolleary/pubsubclient + +# Dependencies + +Install the following libraries using the Arduino IDE: **_Sketch -> Include Library -> Manage Libraries_** and search: + + * [PubSubClient](https://github.com/knolleary/pubsubclient): Arduino Client for MQTT. + * [STM32duino ISM43362-M3G-L44](https://github.com/stm32duino/WiFi-ISM43362-M3G-L44): WiFi library for the B-L475E-IOT01A board. + * [STM32 Ethernet](https://github.com/stm32duino/STM32Ethernet): Ethernet library for STM32 based board with on-board Ethernet connector. + +# Examples + +## mqtt_B-L475E-IOT01A +This example is based on the mqtt_esp8266 provided with PubSubClient library. +It has been modified to use the [STM32duino ISM43362-M3G-L44](https://github.com/stm32duino/WiFi-ISM43362-M3G-L44) WiFi library with [B-L475E-IOT01A](http://www.st.com/en/evaluation-tools/b-l475e-iot01a.html) board + +## mqtt_STM32Ethernet +This example is based on the mqtt_basic provided with PubSubClient library. +It has been modified to use the [STM32 Ethernet](https://github.com/stm32duino/STM32Ethernet) Ethernet library with a STM32 based board +with on-board Ethernet connector. diff --git a/examples/Communication/MQTT/PubSubClient/mqtt_B-L475E-IOT01A/mqtt_B-L475E-IOT01A.ino b/examples/Communication/MQTT/PubSubClient/mqtt_B-L475E-IOT01A/mqtt_B-L475E-IOT01A.ino new file mode 100644 index 0000000..4d15345 --- /dev/null +++ b/examples/Communication/MQTT/PubSubClient/mqtt_B-L475E-IOT01A/mqtt_B-L475E-IOT01A.ino @@ -0,0 +1,141 @@ +/* + Basic B-L475E-IOT01A MQTT example + + This example is based on the mqtt_esp8266 provided with PubSubClient library. + + This sketch demonstrates the capabilities of the pubsub library in combination + with the B-L475E-IOT01A board. + + It connects to an MQTT server then: + - publishes "hello world" to the topic "outTopic" every two seconds + - subscribes to the topic "inTopic", printing out any messages + it receives. NB - it assumes the received payloads are strings not binary + - If the first character of the topic "inTopic" is an 1, switch ON the LED_BUILTIN Led, + else switch it off + + It will reconnect to the server if the connection is lost using a blocking + reconnect function. See the 'mqtt_reconnect_nonblocking' example for how to + achieve the same result without blocking the main loop. +*/ +#include <SPI.h> +#include <WiFiST.h> +#include <PubSubClient.h> + +// Update these with values suitable for your network. +char ssid[] = "......."; +const char* password = "......."; +const char* mqtt_server = "broker.mqtt-dashboard.com"; + +SPIClass SPI_3(PC12, PC11, PC10); +WiFiClass WiFi(&SPI_3, PE0, PE1, PE8, PB13); +WiFiClient STClient; +int status = WL_IDLE_STATUS; // the Wifi radio's status + +PubSubClient client(STClient); +long lastMsg = 0; +char msg[50]; +long value = 0; + +void setup() { + pinMode(LED_BUILTIN, OUTPUT); // Initialize the LED_BUILTIN pin as an output + Serial.begin(115200); + setup_wifi(); + client.setServer(mqtt_server, 1883); + client.setCallback(callback); +} + +void setup_wifi() { + + delay(10); + + // initialize the WiFi module: + if (WiFi.status() == WL_NO_SHIELD) { + Serial.println("WiFi module not detected"); + // don't continue: + while (true); + } + + // print firmware version: + String fv = WiFi.firmwareVersion(); + Serial.print("Firmware version: "); + Serial.println(fv); + + if (fv != "C3.5.2.3.BETA9") { + Serial.println("Please upgrade the firmware"); + } + + // attempt to connect to Wifi network: + Serial.print("Attempting to connect to network: "); + Serial.println(ssid); + while (status != WL_CONNECTED) { + Serial.print("."); + // Connect to WPA2 network: + status = WiFi.begin(ssid, password); + if (status != WL_CONNECTED) { + // Connect to WPA (TKIP) network: + status = WiFi.begin(ssid, password, ES_WIFI_SEC_WPA); + } + // wait 10 seconds for connection: + delay(10000); + } + + Serial.println(); + Serial.println("WiFi connected"); + Serial.println("IP address: "); + Serial.println(WiFi.localIP()); +} + +void callback(char* topic, byte* payload, unsigned int length) { + Serial.print("Message arrived ["); + Serial.print(topic); + Serial.print("] "); + for (unsigned int i = 0; i < length; i++) { + Serial.print((char)payload[i]); + } + Serial.println(); + + // Switch on the LED if an 1 was received as first character + if ((char)payload[0] == '1') { + digitalWrite(LED_BUILTIN, HIGH); // Turn the LED on + } else { + digitalWrite(LED_BUILTIN, LOW); // Turn the LED off + } +} + +void reconnect() { + // Loop until we're reconnected + while (!client.connected()) { + Serial.print("Attempting MQTT connection..."); + // Attempt to connect + if (client.connect("B-L475E-IOT01AClient")) { + Serial.println("connected"); + // Once connected, publish an announcement... + client.publish("outTopic", "hello world"); + // ... and resubscribe + client.subscribe("inTopic"); + } else { + Serial.print("failed, rc="); + Serial.print(client.state()); + Serial.println(" try again in 5 seconds"); + // Wait 5 seconds before retrying + delay(5000); + } + } +} +void loop() { + + if (!client.connected()) { + reconnect(); + } + client.loop(); + + long now = millis(); + if (now - lastMsg > 2000) { + lastMsg = now; + ++value; + snprintf (msg, 50, "hello world #%ld", value); + Serial.print("Publish message: "); + Serial.println(msg); + client.publish("outTopic", msg); + } +} diff --git a/examples/Communication/MQTT/PubSubClient/mqtt_STM32Ethernet/mqtt_STM32Ethernet.ino b/examples/Communication/MQTT/PubSubClient/mqtt_STM32Ethernet/mqtt_STM32Ethernet.ino new file mode 100644 index 0000000..7f77884 --- /dev/null +++ b/examples/Communication/MQTT/PubSubClient/mqtt_STM32Ethernet/mqtt_STM32Ethernet.ino @@ -0,0 +1,100 @@ +/* + Basic STM32 Ethernet MQTT example + + This sketch demonstrates the basic capabilities of the library. + It connects to an MQTT server then: + - publishes "hello world" to the topic "outTopic" every two seconds + - subscribes to the topic "inTopic", printing out any messages + it receives. NB - it assumes the received payloads are strings not binary + + It will reconnect to the server if the connection is lost using a blocking + reconnect function. See the 'mqtt_reconnect_nonblocking' example for how to + achieve the same result without blocking the main loop. + +*/ + +#include <LwIP.h> +#include <STM32Ethernet.h> +#include <PubSubClient.h> + +// Update these with values suitable for your network. +byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED }; +// Set the static IP address to use if the DHCP fails to assign +IPAddress ip(192, 168, 0, 177); +// if you don't want to use DNS (and reduce your sketch size) +// use the numeric IP instead of the name for the server: +//IPAddress server(74,125,232,128); // numeric IP for Google (no DNS) +char server[] = "broker.mqtt-dashboard.com"; // name address for mqtt broker (using DNS) +long lastMsg = 0; +char msg[50]; +long value = 0; + +void callback(char* topic, byte* payload, unsigned int length) { + Serial.print("Message arrived ["); + Serial.print(topic); + Serial.print("] "); + for (unsigned int i=0;i<length;i++) { + Serial.print((char)payload[i]); + } + Serial.println(); +} + +EthernetClient ethClient; +PubSubClient client(ethClient); + +void reconnect() { + + // Loop until we're reconnected + while (!client.connected()) { + Serial.print("Attempting MQTT connection..."); + // Attempt to connect + if (client.connect("arduinoClient72")) { + Serial.println("connected"); + // Once connected, publish an announcement... + client.publish("outTopic","hello world"); + // ... and resubscribe + client.subscribe("inTopic"); + } else { + Serial.print("failed, rc="); + Serial.print(client.state()); + Serial.println(" try again in 5 seconds"); + // Wait 5 seconds before retrying + delay(5000); + } + } +} + +void setup() +{ + Serial.begin(115200); + + client.setServer(server, 1883); + client.setCallback(callback); + + // Start the Ethernet connection: + if (Ethernet.begin(mac) == 0) { + Serial.println("Failed to configure Ethernet using DHCP"); + // Try to congifure using IP address instead of DHCP: + Ethernet.begin(mac, ip); + } + // Allow the hardware to sort itself out + delay(1500); +} + +void loop() +{ + if (!client.connected()) { + reconnect(); + } + client.loop(); + + long now = millis(); + if (now - lastMsg > 2000) { + lastMsg = now; + ++value; + snprintf (msg, 50, "hello world #%ld", value); + Serial.print("Publish message: "); + Serial.println(msg); + client.publish("outTopic", msg); + } +} diff --git a/examples/STM32F746NG-DISCOVERY/Ethernet_MQTT_Adafruit.io/Ethernet_MQTT_Adafruit.io.ino b/examples/STM32F746NG-DISCOVERY/Ethernet_MQTT_Adafruit.io/Ethernet_MQTT_Adafruit.io.ino new file mode 100644 index 0000000..c3030e3 --- /dev/null +++ b/examples/STM32F746NG-DISCOVERY/Ethernet_MQTT_Adafruit.io/Ethernet_MQTT_Adafruit.io.ino @@ -0,0 +1,160 @@ +/* + STM32F746G-DISCOVERY MQTT example to publish on https://io.adafruit.com broker + + See https://learn.adafruit.com/mqtt-adafruit-io-and-you/overview + + This sketch demonstrates the capabilities of the pubsub library in combination + with the STM32F746G-DISCOVERY board. + + It will use several components of the board and you need to install corresponding libraries : + - Ethernet (STM32Ethernet) : https://github.com/stm32duino/STM32Ethernet + - Temperature and humidity sensor (HTS221) : https://github.com/stm32duino/HTS221 + - Arduino Client for MQTT: https://github.com/knolleary/pubsubclient + + To get temperature and humidity you will need the X-NUCLEO-IKS01A1, a motion MEMS and + environmental sensor expansion board for the STM32 board. + + You can find more information on the board and exapansion board here : + http://www.st.com/en/evaluation-tools/32f746gdiscovery.html + http://www.st.com/content/st_com/en/products/ecosystems/stm32-open-development-environment/stm32-nucleo-expansion-boards/stm32-ode-sense-hw/x-nucleo-iks01a1.html) + + You will need to create some feeds in your Adafruit IO Dashboard. + See https://learn.adafruit.com/mqtt-adafruit-io-and-you/getting-started-on-adafruit-io + to know how register and create your Adafruit IO dashboard and feeds: + - hello: Text block + - onoff: Toggle block + - temp: Stream block + - hum: Gauge block + A screenshot of the dashboard is available in the img/ directory: dashboard_adafruit.png + + It connects to the Adafruit IO's MQTT server (a.k.a broker) server then: + - publishes announcement "Hi, I'm STM32 user!" to the topic 'AIO_USERNAME"/feeds/hello"' + - subscribes to the topic AIO_USERNAME"/feeds/onoff"', switching LED_BUILTIN state + - publishes temperature and humidity from the HTS221 sensor to the topic + 'AIO_USERNAME"/feeds/temp"' and 'AIO_USERNAME"/feeds/hum"' every 10 seconds + + It will reconnect to the server if the connection is lost using a blocking + reconnect function. See the 'mqtt_reconnect_nonblocking' example for how to + achieve the same result without blocking the main loop. + +*/ +#include <LwIP.h> +#include <STM32Ethernet.h> +#include <PubSubClient.h> +#include <HTS221Sensor.h> + +// Adafruit.io Setup +#define AIO_SERVER "io.adafruit.com" +#define AIO_SERVERPORT 1883 +#define AIO_USERNAME "......" +#define AIO_KEY "........" + +// Etherrnet setup +// Update these with values suitable for your network. +byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED }; +// Set the static IP address to use if the DHCP fails to assign +IPAddress ip(192, 168, 0, 177); +EthernetClient STClient; + +// i2c sensors +HTS221Sensor *HumTemp; + +PubSubClient client(STClient); +long lastMsg = 0; +char msg[8]; + +void setup() { + pinMode(LED_BUILTIN, OUTPUT); // Initialize the LED_BUILTIN pin as an output + Serial.begin(115200); + + client.setServer(AIO_SERVER, AIO_SERVERPORT); + client.setCallback(callback); + + // Start the Ethernet connection: + if (Ethernet.begin(mac) == 0) { + Serial.println("Failed to configure Ethernet using DHCP"); + // Try to congifure using IP address instead of DHCP: + Ethernet.begin(mac, ip); + } + // Allow the hardware to sort itself out + delay(1500); + + // Initialize I2C bus. + Wire.begin(); + + // Initlialize components. + HumTemp = new HTS221Sensor (&Wire); + HumTemp->Enable(); +} + +void callback(char* topic, byte* payload, unsigned int length) { + +#if 0 + Serial.print("Message arrived ["); + Serial.print(topic); + Serial.print("] "); + for (unsigned int i = 0; i < length; i++) { + Serial.print((char)payload[i]); + } + Serial.println(); +#else + UNUSED(topic); +#endif + if (length > 1) { + // Switch on/off the LED (payload messages can be 'ON' or 'OFF') + if ((char)payload[1] == 'N') { + digitalWrite(LED_BUILTIN, HIGH); // Turn the LED on + } else { + digitalWrite(LED_BUILTIN, LOW); // Turn the LED off + } + } +} + +void reconnect() { + // Loop until we're reconnected + while (!client.connected()) { + Serial.print("Attempting MQTT connection..."); + // Attempt to connect + // Note - the default maximum packet size is 128 bytes. If the + // combined length of clientId, username and password exceed this, + // you will need to increase the value of MQTT_MAX_PACKET_SIZE in + // PubSubClient.h + if (client.connect("STM32Client", AIO_USERNAME, AIO_KEY)) { + Serial.println("connected"); + // Once connected, publish an announcement... + client.publish(AIO_USERNAME"/feeds/hello", "Hi, I'm STM32 user!"); + // ... and resubscribe + client.subscribe(AIO_USERNAME"/feeds/onoff"); + } else { + Serial.print("failed, rc="); + Serial.print(client.state()); + Serial.println(" try again in 5 seconds"); + // Wait 5 seconds before retrying + delay(5000); + } + } +} + +void loop() { + float temperature, humidity; + if (!client.connected()) { + reconnect(); + } + client.loop(); + + long now = millis(); + if (now - lastMsg > 10000) { + lastMsg = now; + HumTemp->GetTemperature(&temperature); + dtostrf(temperature, 2, 2, msg); + Serial.print("Publish temperature "); + Serial.println(msg); + client.publish(AIO_USERNAME"/feeds/temp", msg); + + HumTemp->GetHumidity(&humidity); + snprintf (msg, 8, "%u", (unsigned int)humidity); + Serial.print("Publish humidity "); + Serial.println(msg); + client.publish(AIO_USERNAME"/feeds/hum", msg); + } +} diff --git a/examples/STM32F746NG-DISCOVERY/Ethernet_MQTT_Adafruit.io/README.md b/examples/STM32F746NG-DISCOVERY/Ethernet_MQTT_Adafruit.io/README.md new file mode 100644 index 0000000..a4381ba --- /dev/null +++ b/examples/STM32F746NG-DISCOVERY/Ethernet_MQTT_Adafruit.io/README.md @@ -0,0 +1,39 @@ +# Ethernet_MQTT_Adafruit.io + + This example demonstrates the capabilities of the [PubSubClient](https://github.com/knolleary/pubsubclient) library in combination + with the [STM32F746G-DISCOVERY](http://www.st.com/en/evaluation-tools/32f746gdiscovery.html) board to publish on https://io.adafruit.com broker + + See https://learn.adafruit.com/mqtt-adafruit-io-and-you/overview + +# Dependencies + +Install the following libraries using the Arduino IDE: **_Sketch -> Include Library -> Manage Libraries_** and search: + + * [PubSubClient](https://github.com/knolleary/pubsubclient): Arduino Client for MQTT. + * [STM32 Ethernet](https://github.com/stm32duino/STM32Ethernet): Ethernet library for STM32 based board with on-board Ethernet connector. + * [STM32duino HTS221](https://github.com/stm32duino/HTS221): Ethernet library for STM32 based board with on-board Ethernet connector. + +# Hardware + +To get temperature and humidity you will need the [X-NUCLEO-IKS01A1](http://www.st.com/content/st_com/en/products/ecosystems/stm32-open-development-environment/stm32-nucleo-expansion-boards/stm32-ode-sense-hw/x-nucleo-iks01a1.html), a motion MEMS and environmental sensor expansion board for the STM32 board. + +# Adafruit IO Dashboard. + + You will need to create some feeds in your Adafruit IO Dashboard. + + See https://learn.adafruit.com/mqtt-adafruit-io-and-you/getting-started-on-adafruit-io + + to know how register and create your Adafruit IO dashboard and feeds: + * hello: Text block + * onoff: Toggle block + * temp: Stream block + * hum: Gauge block + + A screenshot of the dashboard: + [[/img/dashboard_adafruit.png|alt="Dashboard Adafruit"]] + + It connects to the Adafruit IO's MQTT server (a.k.a broker) server then: + * publishes announcement "_Hi, I'm STM32 user!_" to the topic `AIO_USERNAME"/feeds/hello"` + * subscribes to the topic `AIO_USERNAME"/feeds/onoff"`, switching `LED_BUILTIN` state + * publishes temperature and humidity from the HTS221 sensor to the topic + `AIO_USERNAME"/feeds/temp"` and `AIO_USERNAME"/feeds/hum"` every 10 seconds diff --git a/examples/STM32L475VG-DISCOVERY-IOT/WiFi_MQTT_Adafruit.io/README.md b/examples/STM32L475VG-DISCOVERY-IOT/WiFi_MQTT_Adafruit.io/README.md new file mode 100644 index 0000000..9923b2d --- /dev/null +++ b/examples/STM32L475VG-DISCOVERY-IOT/WiFi_MQTT_Adafruit.io/README.md @@ -0,0 +1,35 @@ +# WiFi_MQTT_Adafruit.io + + This example demonstrates the capabilities of the [PubSubClient](https://github.com/knolleary/pubsubclient) library in combination + with the [B-L475E-IOT01A](http://www.st.com/en/evaluation-tools/b-l475e-iot01a.html) board to publish on https://io.adafruit.com broker + + See https://learn.adafruit.com/mqtt-adafruit-io-and-you/overview + +# Dependencies + +Install the following libraries using the Arduino IDE: **_Sketch -> Include Library -> Manage Libraries_** and search: + + * [PubSubClient](https://github.com/knolleary/pubsubclient): Arduino Client for MQTT. + * [STM32duino ISM43362-M3G-L44](https://github.com/stm32duino/WiFi-ISM43362-M3G-L44): WiFi library for the [B-L475E-IOT01A](http://www.st.com/en/evaluation-tools/b-l475e-iot01a.html) board. + * [STM32duino HTS221](https://github.com/stm32duino/HTS221): Ethernet library for STM32 based board with on-board Ethernet connector. + +# Adafruit IO Dashboard. + + You will need to create some feeds in your Adafruit IO Dashboard. + + See https://learn.adafruit.com/mqtt-adafruit-io-and-you/getting-started-on-adafruit-io + + to know how register and create your Adafruit IO dashboard and feeds: + * hello: Text block + * onoff: Toggle block + * temp: Stream block + * hum: Gauge block + + A screenshot of the dashboard: + [[/img/dashboard_adafruit.png|alt="Dashboard Adafruit"]] + + It connects to the Adafruit IO's MQTT server (a.k.a broker) server then: + * publishes announcement "_Hi, I'm STM32 user!_" to the topic `AIO_USERNAME"/feeds/hello"` + * subscribes to the topic `AIO_USERNAME"/feeds/onoff"`, switching `LED_BUILTIN` state + * publishes temperature and humidity from the HTS221 sensor to the topic + `AIO_USERNAME"/feeds/temp"` and `AIO_USERNAME"/feeds/hum"` every 10 seconds diff --git a/examples/STM32L475VG-DISCOVERY-IOT/WiFi_MQTT_Adafruit.io/WiFi_MQTT_Adafruit.io.ino b/examples/STM32L475VG-DISCOVERY-IOT/WiFi_MQTT_Adafruit.io/WiFi_MQTT_Adafruit.io.ino new file mode 100644 index 0000000..0c42ccf --- /dev/null +++ b/examples/STM32L475VG-DISCOVERY-IOT/WiFi_MQTT_Adafruit.io/WiFi_MQTT_Adafruit.io.ino @@ -0,0 +1,193 @@ +/* + B-L475E-IOT01A MQTT example to publish on https://io.adafruit.com broker + + See https://learn.adafruit.com/mqtt-adafruit-io-and-you/overview + + This sketch demonstrates the capabilities of the pubsub library in combination + with the B-L475E-IOT01A board. + + It will use several components of the board and you need to install corresponding libraries : + - WiFi (ISM43362-M3G-L44) : https://github.com/stm32duino/WiFi-ISM43362-M3G-L44 + - Temperature and humidity sensor (HTS221) : https://github.com/stm32duino/HTS221 + - Arduino Client for MQTT: https://github.com/knolleary/pubsubclient + + You can find more information on this board here : + http://www.st.com/en/evaluation-tools/b-l475e-iot01a.html + + You will need to create some feeds in your Adafruit IO Dashboard. + See https://learn.adafruit.com/mqtt-adafruit-io-and-you/getting-started-on-adafruit-io + to know how register and create your Adafruit IO dashboard and feeds: + - hello: Text block + - onoff: Toggle block + - temp: Stream block + - hum: Gauge block + A screenshot of the dashboard is available in the sketch directory: dashboard_adafruit.png + + It connects to the Adafruit IO's MQTT server (a.k.a broker) server then: + - publishes announcement "Hi, I'm STM32 user!" to the topic 'AIO_USERNAME"/feeds/hello"' + - subscribes to the topic AIO_USERNAME"/feeds/onoff"', switching LED_BUILTIN state + - publishes temperature and humidity from the HTS221 sensor to the topic + 'AIO_USERNAME"/feeds/temp"' and 'AIO_USERNAME"/feeds/hum"' every 10 seconds + + It will reconnect to the server if the connection is lost using a blocking + reconnect function. See the 'mqtt_reconnect_nonblocking' example for how to + achieve the same result without blocking the main loop. + +*/ +#include <SPI.h> +#include <WiFiST.h> +#include <PubSubClient.h> +#include <HTS221Sensor.h> + +// Update these with values suitable for your network. +char ssid[] = "......."; +const char* password = "........"; + +// Adafruit.io Setup +#define AIO_SERVER "io.adafruit.com" +#define AIO_SERVERPORT 1883 +#define AIO_USERNAME "......" +#define AIO_KEY "........" + +// WiFi module setup +SPIClass SPI_3(PC12, PC11, PC10); +WiFiClass WiFi(&SPI_3, PE0, PE1, PE8, PB13); +WiFiClient STClient; +int status = WL_IDLE_STATUS; // the Wifi radio's status + +// i2c sensors +HTS221Sensor *HumTemp; + +TwoWire *dev_i2c; +#define I2C2_SCL PB10 +#define I2C2_SDA PB11 + + +PubSubClient client(STClient); +long lastMsg = 0; +char msg[8]; + +void setup() { + pinMode(LED_BUILTIN, OUTPUT); // Initialize the LED_BUILTIN pin as an output + Serial.begin(115200); + setup_wifi(); + client.setServer(AIO_SERVER, AIO_SERVERPORT); + client.setCallback(callback); + + // Initialize I2C bus. + dev_i2c = new TwoWire(I2C2_SDA, I2C2_SCL); + dev_i2c->begin(); + + // Initlialize components. + HumTemp = new HTS221Sensor (dev_i2c); + HumTemp->Enable(); +} + +void setup_wifi() { + + delay(10); + + // Initialize the WiFi module: + if (WiFi.status() == WL_NO_SHIELD) { + Serial.println("WiFi module not detected"); + // don't continue: + while (true); + } + + // Print firmware version: + String fv = WiFi.firmwareVersion(); + Serial.print("Firmware version: "); + Serial.println(fv); + + if (fv != "C3.5.2.3.BETA9") { + Serial.println("Please upgrade the firmware"); + } + + // Attempt to connect to Wifi network: + Serial.print("Attempting to connect to network: "); + Serial.println(ssid); + while (status != WL_CONNECTED) { + Serial.print("."); + // Connect to network: + status = WiFi.begin(ssid, password); + // Wait 10 seconds for connection: + delay(10000); + } + + Serial.println(); + Serial.println("WiFi connected"); + Serial.println("IP address: "); + Serial.println(WiFi.localIP()); +} + +void callback(char* topic, byte* payload, unsigned int length) { + +#if 0 + Serial.print("Message arrived ["); + Serial.print(topic); + Serial.print("] "); + for (unsigned int i = 0; i < length; i++) { + Serial.print((char)payload[i]); + } + Serial.println(); +#else + UNUSED(topic); +#endif + if (length > 1) { + // Switch on/off the LED (payload messages can be 'ON' or 'OFF') + if ((char)payload[1] == 'N') { + digitalWrite(LED_BUILTIN, HIGH); // Turn the LED on + } else { + digitalWrite(LED_BUILTIN, LOW); // Turn the LED off + } + } +} + +void reconnect() { + // Loop until we're reconnected + while (!client.connected()) { + Serial.print("Attempting MQTT connection..."); + // Attempt to connect + // Note - the default maximum packet size is 128 bytes. If the + // combined length of clientId, username and password exceed this, + // you will need to increase the value of MQTT_MAX_PACKET_SIZE in + // PubSubClient.h + if (client.connect("STM32Client", AIO_USERNAME, AIO_KEY)) { + Serial.println("connected"); + // Once connected, publish an announcement... + client.publish(AIO_USERNAME"/feeds/hello", "Hi, I'm STM32 user!"); + // ... and resubscribe + client.subscribe(AIO_USERNAME"/feeds/onoff"); + } else { + Serial.print("failed, rc="); + Serial.print(client.state()); + Serial.println(" try again in 5 seconds"); + // Wait 5 seconds before retrying + delay(5000); + } + } +} + +void loop() { + float temperature, humidity; + if (!client.connected()) { + reconnect(); + } + client.loop(); + + long now = millis(); + if (now - lastMsg > 10000) { + lastMsg = now; + HumTemp->GetTemperature(&temperature); + dtostrf(temperature, 2, 2, msg); + Serial.print("Publish temperature "); + Serial.println(msg); + client.publish(AIO_USERNAME"/feeds/temp", msg); + + HumTemp->GetHumidity(&humidity); + snprintf (msg, 8, "%u", (unsigned int)humidity); + Serial.print("Publish humidity "); + Serial.println(msg); + client.publish(AIO_USERNAME"/feeds/hum", msg); + } +} diff --git a/img/dashboard_adafruit.png b/img/dashboard_adafruit.png new file mode 100644 index 0000000000000000000000000000000000000000..821f8ccfe172768050873f5cbe5954f02f9b1052 GIT binary patch literal 30115 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 literal 0 HcmV?d00001 From d6fa824ac525c8c2ae550e2dc0422bfcd6a7fd38 Mon Sep 17 00:00:00 2001 From: "Frederic.Pillon" <frederic.pillon@st.com> Date: Wed, 7 Mar 2018 11:30:37 +0100 Subject: [PATCH 5/5] Move boards example in Boards directory Signed-off-by: Frederic.Pillon <frederic.pillon@st.com> --- .../Ethernet_MQTT_Adafruit.io/Ethernet_MQTT_Adafruit.io.ino | 0 .../STM32F746NG-DISCOVERY/Ethernet_MQTT_Adafruit.io/README.md | 0 .../BTLE_sensors_TimeOfFlight_demo.ino | 0 .../STM32L475VG-DISCOVERY-IOT/WiFi_MQTT_Adafruit.io/README.md | 0 .../WiFi_MQTT_Adafruit.io/WiFi_MQTT_Adafruit.io.ino | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename examples/{ => Boards}/STM32F746NG-DISCOVERY/Ethernet_MQTT_Adafruit.io/Ethernet_MQTT_Adafruit.io.ino (100%) rename examples/{ => Boards}/STM32F746NG-DISCOVERY/Ethernet_MQTT_Adafruit.io/README.md (100%) rename examples/{ => Boards}/STM32L475VG-DISCOVERY-IOT/BTLE_sensors_TimeOfFlight_demo/BTLE_sensors_TimeOfFlight_demo.ino (100%) rename examples/{ => Boards}/STM32L475VG-DISCOVERY-IOT/WiFi_MQTT_Adafruit.io/README.md (100%) rename examples/{ => Boards}/STM32L475VG-DISCOVERY-IOT/WiFi_MQTT_Adafruit.io/WiFi_MQTT_Adafruit.io.ino (100%) diff --git a/examples/STM32F746NG-DISCOVERY/Ethernet_MQTT_Adafruit.io/Ethernet_MQTT_Adafruit.io.ino b/examples/Boards/STM32F746NG-DISCOVERY/Ethernet_MQTT_Adafruit.io/Ethernet_MQTT_Adafruit.io.ino similarity index 100% rename from examples/STM32F746NG-DISCOVERY/Ethernet_MQTT_Adafruit.io/Ethernet_MQTT_Adafruit.io.ino rename to examples/Boards/STM32F746NG-DISCOVERY/Ethernet_MQTT_Adafruit.io/Ethernet_MQTT_Adafruit.io.ino diff --git a/examples/STM32F746NG-DISCOVERY/Ethernet_MQTT_Adafruit.io/README.md b/examples/Boards/STM32F746NG-DISCOVERY/Ethernet_MQTT_Adafruit.io/README.md similarity index 100% rename from examples/STM32F746NG-DISCOVERY/Ethernet_MQTT_Adafruit.io/README.md rename to examples/Boards/STM32F746NG-DISCOVERY/Ethernet_MQTT_Adafruit.io/README.md diff --git a/examples/STM32L475VG-DISCOVERY-IOT/BTLE_sensors_TimeOfFlight_demo/BTLE_sensors_TimeOfFlight_demo.ino b/examples/Boards/STM32L475VG-DISCOVERY-IOT/BTLE_sensors_TimeOfFlight_demo/BTLE_sensors_TimeOfFlight_demo.ino similarity index 100% rename from examples/STM32L475VG-DISCOVERY-IOT/BTLE_sensors_TimeOfFlight_demo/BTLE_sensors_TimeOfFlight_demo.ino rename to examples/Boards/STM32L475VG-DISCOVERY-IOT/BTLE_sensors_TimeOfFlight_demo/BTLE_sensors_TimeOfFlight_demo.ino diff --git a/examples/STM32L475VG-DISCOVERY-IOT/WiFi_MQTT_Adafruit.io/README.md b/examples/Boards/STM32L475VG-DISCOVERY-IOT/WiFi_MQTT_Adafruit.io/README.md similarity index 100% rename from examples/STM32L475VG-DISCOVERY-IOT/WiFi_MQTT_Adafruit.io/README.md rename to examples/Boards/STM32L475VG-DISCOVERY-IOT/WiFi_MQTT_Adafruit.io/README.md diff --git a/examples/STM32L475VG-DISCOVERY-IOT/WiFi_MQTT_Adafruit.io/WiFi_MQTT_Adafruit.io.ino b/examples/Boards/STM32L475VG-DISCOVERY-IOT/WiFi_MQTT_Adafruit.io/WiFi_MQTT_Adafruit.io.ino similarity index 100% rename from examples/STM32L475VG-DISCOVERY-IOT/WiFi_MQTT_Adafruit.io/WiFi_MQTT_Adafruit.io.ino rename to examples/Boards/STM32L475VG-DISCOVERY-IOT/WiFi_MQTT_Adafruit.io/WiFi_MQTT_Adafruit.io.ino