Mxchip IOT dev kit receiving data from IOT hub - iot

I just started playing with the mxchip. I want my device to trigger an alarm when receiving some command. It seems to me all examples I found are device collecting info and send to iot hub. Can mxchip receive data from iothub or azure function? And maybe some guidance on getting started?

Yes, assuming you use the SDK from the examples for the MXChip you have those handlers available:
DevKitMQTTClient_SetMessageCallback(MessageCallback);
DevKitMQTTClient_SetDeviceMethodCallback(DeviceMethodCallback);
Examples:
static void MessageCallback(const char *payLoad, int size)
{
Screen.print(1, payLoad, true);
}
static int DeviceMethodCallback(const char *methodName, const unsigned char *payload,
int size, unsigned char **response, int *response_size)
{
LogInfo("Try to invoke method %s", methodName);
// Do your logic...
int result = 200;
return result;
}

Yes. Its possible to send messages to device ( Cloud-to-device) from IOT Hub.
Here is some example mentioned in these links
https://learn.microsoft.com/en-us/azure/iot-hub/iot-hub-csharp-csharp-c2d
https://learn.microsoft.com/en-us/azure/iot-hub/iot-hub-devguide-messaging

Related

cannot publish data to my local mqtt server

Please i wish somebody could help me with this. I've been struggling into it since a couple of weeks, i am so new to that.
I want to send data from ESP32 SIM800L to a mqtt broker.
The mqtt server is running on my local machine and the ESP32 SIM800 can perfectly connect to APN.
I saw many tutorials doing it with WIFI connection but not GPRS(what i am using).
I finally find this: tinyGSM and this :arduino mqtt mongodb
And i adapted it as follows, but still getting connection failed:
// Your GPRS credentials (leave empty, if not needed)
const char apn[] = "internet.tn"; // APN (example: internet.vodafone.pt) use https://wiki.apnchanger.org
const char gprsUser[] = ""; // GPRS User
const char gprsPass[] = ""; // GPRS Password
// SIM card PIN (leave empty, if not defined)
const char simPIN[] = "";
uint32_t lastReconnectAttempt = 0;
// TTGO T-Call pins
#define MODEM_RST 5
#define MODEM_PWKEY 4
#define MODEM_POWER_ON 23
#define MODEM_TX 27
#define MODEM_RX 26
#define I2C_SDA 21
#define I2C_SCL 22
// Set serial for debug console (to Serial Monitor, default speed 115200)
#define SerialMon Serial
// Set serial for AT commands (to SIM800 module)
#define SerialAT Serial1
// Configure TinyGSM library
#define TINY_GSM_MODEM_SIM800 // Modem is SIM800
#define TINY_GSM_RX_BUFFER 1024 // Set RX buffer to 1Kb
#include <Wire.h>
#include <TinyGsmClient.h>
#include <PubSubClient.h>
#ifdef DUMP_AT_COMMANDS
#include <StreamDebugger.h>
StreamDebugger debugger(SerialAT, SerialMon);
TinyGsm modem(debugger);
#else
TinyGsm modem(SerialAT);
#endif
// I2C for SIM800 (to keep it running when powered from battery)
TwoWire I2CPower = TwoWire(0);
const char* broker = "localhost";
const char* topicInit = "GsmClientTest/init";
// Function prototypes
void subscribeReceive(char* topic, byte* payload, unsigned int length);
// TinyGSM Client for Internet connection
// gsm and MQTT related objects
TinyGsmClient client(modem);
PubSubClient mqtt(client);
long mqtttimer = 0; // Timer for counting 5 seconds and retrying mqtt connection
byte mqtttarea = 1;
#define uS_TO_S_FACTOR 1000000 /* Conversion factor for micro seconds to seconds */
#define TIME_TO_SLEEP 3600 /* Time ESP32 will go to sleep (in seconds) 3600 seconds = 1 hour */
void mqttCallback(char* topic, byte* payload, unsigned int len) {
SerialMon.print("Message arrived [");
SerialMon.print(topic);
SerialMon.print("]: ");
SerialMon.write(payload, len);
SerialMon.println();}
boolean mqttConnect() {
SerialMon.print("Connecting to ");
SerialMon.print(broker);
// Connect to MQTT Broker
boolean status = mqtt.connect("GsmClientTest");
// Or, if you want to authenticate MQTT:
//boolean status = mqtt.connect("GsmClientName", "mqtt_user", "mqtt_pass");
if (status == false) {
SerialMon.println(" fail");
return false;
}
SerialMon.println(" success");
mqtt.publish(topicInit, "GsmClientTest started");
// mqtt.subscribe(topicLed);
return mqtt.connected();}
void setup() {
SerialMon.begin(9600);
// Start I2C communication
I2CPower.begin(I2C_SDA, I2C_SCL, 400000);
// Set modem reset, enable, power pins
pinMode(MODEM_PWKEY, OUTPUT);
pinMode(MODEM_RST, OUTPUT);
pinMode(MODEM_POWER_ON, OUTPUT);
digitalWrite(MODEM_PWKEY, LOW);
digitalWrite(MODEM_RST, HIGH);
digitalWrite(MODEM_POWER_ON, HIGH);
// Set GSM module baud rate and UART pins
SerialAT.begin(9600, SERIAL_8N1, MODEM_RX, MODEM_TX);
delay(3000);
// Restart SIM800 module, it takes quite some time
// To skip it, call init() instead of restart()
SerialMon.println("Initializing modem...");
modem.restart();
// use modem.init() if you don't need the complete restart
// Unlock your SIM card with a PIN if needed
if (strlen(simPIN) && modem.getSimStatus() != 3 ) {
modem.simUnlock(simPIN);
}
SerialMon.print("Connecting to APN: ");
SerialMon.print(apn);
if (!modem.gprsConnect(apn, gprsUser, gprsPass)) {
SerialMon.println(" fail");
}
else {
SerialMon.println(" OK");
}
// MQTT Broker setup
mqtt.setServer(broker, 1883);
mqtt.setCallback(mqttCallback);
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
}
void loop() {
// This is needed at the top of the loop!
if (!mqtt.connected()) {
SerialMon.println("=== MQTT NOT CONNECTED ===");
// Reconnect every 10 seconds
uint32_t t = millis();
if (t - lastReconnectAttempt > 10000L) {
lastReconnectAttempt = t;
if (mqttConnect()) {
lastReconnectAttempt = 0;
}
}
delay(100);
return;
}
mqtt.publish(topicInit, "Hello");
mqtt.loop();
}
You set the broker's name to localhost:
const char* broker = "localhost";
localhost and the IP address 127.0.0.1 mean "the host that this code is running on". When you're typing commands on the computer running the broker, localhost will mean that computer. There's no way it will work on the ESP32.
You need to name or IP address of the computer running the broker. How you find that will depend on the operating system you're running.
If that computer is on your local network it's probably using a private IP address like 10.0.1.x or 192.168.1.x. If that's the case you'll need to either use port forwarding in your router to forward packets to it (and then you'll use your router's IP address and not your broker's).
If you're using your router's IP address, that can change without warning, so you'll need to use something like Dynamic DNS to keep up to date with its current IP address.
You'll likely be better off running the broker outside of your network on a cloud-based virtual server or by using one of the several commercial MQTT services out there. Most of them have a free tier which will allow a reasonable amount of traffic per month.
Regardless, localhost will never work here. You need the real, public IP address or name of your broker.

How do I initialize LwIP to use MQTT library

I've looked and followed documentation from LwIP 2.0.2. My project contains the MQTT library supplied in the LwIP 2.0.2. I also found some help at https://dzone.com/articles/mqtt-with-lwip-and-the-nxp-frdm-k64f. I'm unable to get a connection, I've used free public MQTT broker but no hope in connection. I can ping my device. Am I doing something wrong?
static void mqtt_test(mqtt_client_t *mqtt_client)
if (mqtt_client_is_connected(&mqtt_client) == 1)
{
example_subscribe(&mqtt_client, NULL);
} else {
mqtt_do_connect(&mqtt_client);
}
}
when I call this method it always enters mqtt_do_connect() never connecting. Here is mqtt_do_connect
static void mqtt_do_connect(mqtt_client_t *mqtt_client)
{
ip4_addr_t broker_ipaddr;
struct mqtt_connect_client_info_t ci;
err_t err;
if (ipaddr_aton("52.58.177.181", &broker_ipaddr))
{
err = ERR_OK;
}
/* Setup an empty client info structure */
memset( & ci, 0, sizeof(ci));
/* Minimal amount of information required is client identifier, so set it here */
ci.client_id = "test";
/* Initiate client and connect to server, if this fails immediately an error code is returned
otherwise mqtt_connection_cb will be called with connection result after attempting
to establish a connection with the server.
For now MQTT version 3.1.1 is always used */
err = mqtt_client_connect(mqtt_client, & broker_ipaddr, 1883, mqtt_connection_cb, 0, & ci);
/* For now just print the result code if something goes wrong */
if (err != ERR_OK) {
printf("mqtt_connect return %d\n", err);
}
}
I've also noticed in the method mqtt_client_connect in mqtt.c that this exists:
/* Any local address, pick random local port number */
err = tcp_bind(client->conn, IP_ADDR_ANY, 0);
why is this needed? If I replace IP_ADDR_ANY to my local address of the static IP of the device it runs through without throwing a error but no callback mqtt_connection_cb is then called.
I've also initialized the TCP/IP stack as mentioned with static IP. I'm using NO_SYS as 1 but will move it over to FreeRTOS but baby steps first.
I haven't found much support on MQTT in LwIP implementation, am I missing something obvious, any help will be appreciated.
I've used MQTTfx to run a test or two on the broker with good response but nothing from my embedded device (Atmel SAME54).
I've found the solution. I ran my TCP setup in a FreeRTOS thread and opened a socket
static void mqtt_start(void *p)
{
struct sockaddr_in address;
int s_create, new_socket;
int addrlen = sizeof(address);
int opt = 1;
int socket_check;
sys_sem_t sem;
err_t err_sem;
err_sem = sys_sem_new(&sem, 0); /* Create a new semaphore. */
tcpip_init(tcpip_init_done, &sem);
sys_sem_wait(&sem); /* Block until the lwIP stack is initialized. */
sys_sem_free(&sem); /* Free the semaphore. */
/*Create a socket*/
s_create = socket(AF_INET, 1, 0);
setsockopt(s_create, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt));
address.sin_family = AF_INET;
address.sin_addr.s_addr = htonl(IPADDR_ANY);
address.sin_port = htons(HTTP_PORT);
/* bind the connection to port */
socket_check = bind(s_create, (struct sockaddr *)&address, sizeof(address));
if (socket_check < 0) {
LWIP_DEBUGF(LWIP_DBG_ON, ("Bind error=%d\n", socket_check));
goto socket_close;
}
/* tell the connection to listen for incoming connection requests */
listen(s_create, 3);
mqtt_connect(&mqtt_client);
for (;;) {
new_socket = accept(s_create, (struct sockaddr *)&address, (socklen_t *)&addrlen);
socket_close:
close(new_socket);
}
}
I also had a problem with my initialization of my mqtt client, placed a watch on it and saw the struct wasn't initializing. I initialized it globally
mqtt_client_t mqtt_client;
Then use it later in mqtt_start.

I can not subscribe with ESP8266-ESP32 in IBM Watson IOT

I want to subscribe to the "iot-2/evt/status/fmt/json" topic with ESP8266 on IBM Watson IOT. The connection is established but it is disconnecting again. So, reconnecting the MQTT client to … and subscribe to iot-2 / cmd / + / fmt / + OK. This cycle continues. Why is the connection broken?
My ESP8266 code is as follows.
I used an ESP8266-12E NodeMCU, I’ve created an Android app for the publisher.
/*
Basic ESP8266 MQTT example
This sketch demonstrates the capabilities of the pubsub library in combination
with the ESP8266 board/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
- If the first character of the topic "inTopic" is an 1, switch ON the ESP 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.
To install the ESP8266 board, (using Arduino 1.6.4+):
- Add the following 3rd party board manager under "File -> Preferences -> Additional Boards Manager URLs":
http://arduino.esp8266.com/stable/package_esp8266com_index.json
- Open the "Tools -> Board -> Board Manager" and click install for the ESP8266"
- Select your ESP8266 in "Tools -> Board"
*/
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
//#include <ESP8266HTTPClient.h>
#include <SPI.h>
#include <ArduinoJson.h>
#include <PubSubClient.h>
// Update these with values suitable for your network.
//ZYxel
#define ssid "......."
#define password ".................."
//GES ARGE
#define ssid2 "..............." // WiFi SSID
#define password2 "............." // WiFi password
#define spi_ss_pin SS
#define ORG "............"
#define DEVICE_TYPE "........."
#define DEVICE_ID "..........."
#define TOKEN "................"
//-------- Customise the above values --------
char server[] = ORG ".messaging.internetofthings.ibmcloud.com";
int mqttPort=1883;
const char topic[] = "iot-2/cmd/status/fmt/json"; //"iot-2/cmd/status/fmt/json";
char authMethod[] = "use-token-auth";
char token[] = TOKEN;
char clientId[] = "d:" ORG ":" DEVICE_TYPE ":" DEVICE_ID;
WiFiClient wifiClient;
void callback(char* topic, byte* payload, unsigned int payloadLength) ;
PubSubClient client(server, 1883, callback, wifiClient);
void setup() {
Serial.begin(115200);
Serial.println();
wifiConnect();
mqttConnect();
}
void loop() {
if (!client.loop()) {
mqttConnect();
}
}
void wifiConnect() {
Serial.print("Connecting to "); Serial.print(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.print("nWiFi connected, IP address: "); Serial.println(WiFi.localIP());
}
void mqttConnect() {
if (!client.connected()) {
Serial.print("Reconnecting MQTT client to "); Serial.println(server);
while (!client.connect(clientId, authMethod, token)) {
Serial.print(".");
delay(500);
}
initManagedDevice();
Serial.println();
}
}
void initManagedDevice() {
if (client.subscribe(topic)) {
Serial.println("subscribe to cmd OK");
} else {
Serial.println("subscribe to cmd FAILED");
}
}
void callback(char* topic, byte* payload, unsigned int payloadLength) {
Serial.print("callback invoked for topic: "); Serial.println(topic);
for (int i = 0; i < payloadLength; i++) {
Serial.print((char)payload[i]);
}
}
A device ("use-token-auth" authentication type) cannot subscribe to a topic like "iot-2/evt/status/fmt/json" only "iot-2/cmd/status/fmt/json" is allowed.
What you need to do is to generate an API key and token and authenticate as an application:
The following example shows a typical API key:
a-orgId-a84ps90Ajs
The following example shows a typical authentication token:
MP$08VKz!8rXwnR-Q*
When you make an MQTT connection by using an API key, ensure that the following guidelines are applied:
The MQTT client ID is in the format: a:orgId:appId
The MQTT user name is the API key (for example, a-orgId-a84ps90Ajs)
The MQTT password is the authentication token (for example, MP$08VKz!8rXwnR-Q*)
After that you can subscribe to topic like iot-2/type/device_type/id/device_id/evt/event_id/fmt/format_string. So it should be:
iot-2/type/yourDeviceType/id/yourDeviceId/evt/status/fmt/json
You can use the same for commands: this how the topic should look like
iot-2/type/device_type/id/device_id/cmd/command_id/fmt/format_string

iOS app crash while send msg by socket

I use this method for send msg to server
ssize_t send(int, const void *, size_t, int) __DARWIN_ALIAS_C(send);
This is standard Lib from Apple (socket.h and socket.m )
NSString *msg = #"Message want to send";
// socketFileDescriptor is int
NSData *wdata = [msg dataUsingEncoding:NSUTF8StringEncoding];
ssize_t n;
const UInt8 *buf = (const UInt8 *)[wdata bytes];
n = send(socketFileDescriptor, buf,[wdata length],0); // I really sure,it's crash at this statement on device iPad Air, iPad Air2 only
BUT on debug mode isn't not crash!
App will crash when I archive project to IPA (Ad-Hoc Mode)
I have no ideal for this case please help me.
This is more information
I use this method for connect to server
I have already assign value for self.host and self.port variable.
(I sure it can be connect normally in debug mode)
http://pastebin.com/raw.php?i=KFKJsJHZ
and I use this method for send message to server
http://pastebin.com/raw.php?i=Z7Js2JT8
2 method in same class BSDSocket
Please tell me If you want more information.
Thank you

Cannot upload data get xivelyclient.put returned -1

Background:
I am trying to upload data from a simple on off sensor to learn the Xively methods. I am using an Arduino Uno with a WiFi Shield. I made some simple alterations to an example sketch from the Xively library to keep it very simple. I have read the documentation and the FAQ's plus searched the web. There was a similar question (Can't connect to Xively using Arduino + wifi shield, "ret = -1 No sockets available) and the answer was to reduce the number of libraries loaded. I'm using the same library list recommended in that post.I have also updated my Arduino IDE and downloaded the latest xively and HTTP library. The code compiles without error. I re-loaded my device on the xively website and got a new API key and number as well. Plus, I ensured the channel was added with the correct sensor name. I have also checked my router and ensured the WiFi shield was connecting properly.
Problem: I can't see the data on the Xively website and I keep getting the following error messages on the serial monitor from the Arduino:
xivelyclint.put returned -1
also, after several tries, I get "No socket available"
Question: Is there an problem with the code or is it something else?
Current Arduino code (actual ssid, password and API key and number removed):
#include <SPI.h>
#include <WiFi.h>
#include <HttpClient.h>
#include <Xively.h>
char ssid[] = "ssid"; // your network SSID (name)
char pass[] = "password"; // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0; // your network key Index number (needed only for WEP)
int status = WL_IDLE_STATUS;
// Your Xively key to let you upload data
char xivelyKey[] = "api_key";
// Analog pin which we're monitoring (0 and 1 are used by the Ethernet shield)
int sensorPin = 2;
// Define the strings for our datastream IDs
char sensorId[] = "sensor_id";
XivelyDatastream datastreams[] = {
XivelyDatastream(sensorId, strlen(sensorId), DATASTREAM_INT),
};
// Finally, wrap the datastreams into a feed
XivelyFeed feed(feed no., datastreams, 1 /* number of datastreams */);
WiFiClient client;
XivelyClient xivelyclient(client);
void printWifiStatus() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print your WiFi shield's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
}
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
Serial.println("Starting single datastream upload to Xively...");
Serial.println();
// attempt to connect to Wifi network:
while ( status != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
status = WiFi.begin(ssid, pass);
// wait 10 seconds for connection:
delay(10000);
}
Serial.println("Connected to wifi");
printWifiStatus();
}
void loop() {
int sensorValue = digitalRead(sensorPin);
datastreams[0].setInt(sensorValue);
Serial.print("Read sensor value ");
Serial.println(datastreams[0].getInt());
Serial.println("Uploading it to Xively");
int ret = xivelyclient.put(feed, xivelyKey);
Serial.print("xivelyclient.put returned ");
Serial.println(ret);
Serial.println();
delay(15000);
}

Resources