I have a little problem about paho mqtt library.
I register a callback function MQTTClient_messageArrived and MQTTClient_connectionLost.
And I call MQTTClient_subscribe() or MQTTClient_unsubscribe() in this callback function. After running this callback function. I got a error code (-3) from MQTTClient_connectionLost. Furthermore, I print the cause is NULL.
Is any possible problem to my problem? Thanks
Here are my initialize function and callback function:
void mqtt_initialize(void){
int rc;
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
if(MQTTClient_create(&g_MQTT_client, BROKER_ADDR, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL) < 0){
g_mqtt_exist = MQTT_INSTANCE_NOT_EXIST;
} else {
g_mqtt_exist = MQTT_INSTANCE_EXIST;
}
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1;
MQTTClient_setCallbacks(g_MQTT_client, NULL, mqtt_connlost_cb, mqtt_arrived_cb, mqtt_delivered_cb);
if ((rc = MQTTClient_connect(g_MQTT_client, &conn_opts)) != MQTTCLIENT_SUCCESS) {
MAIN_PRINT_DEBUG(0, "Failed to connect MQTT broker, return code %d\n", rc);
mqtt_free();
}
/* set subscribe control topic */
MQTTClient_subscribe(g_MQTT_client, "topic_1", MQTT_QOS);
}
int mqtt_arrived_cb(void *context, char *topicName, int topicLen, MQTTClient_message *message)
{
int ret = 0;
printf("topic: %s\n", topicName);
if(!strcmp(topicName, "topic_1")){
printf("topic_1\n");
ret = MQTTClient_subscribe(g_MQTT_client, "topic_2", 0);
if (ret < 0){
printf("mqtt operation fail\n");
}
}
return 1;
}
void mqtt_connlost_cb(void *context, char *cause)
{
MAIN_PRINT_DEBUG(0, "\n MQTT Connection lost\n");
MAIN_PRINT_DEBUG(0," cause: %s\n", cause);
}
Did you try connecting any other client to same broker with same client id? That could be a possible case if you are getting connection lost. Also if your callback throws exception, it will cause connection lost, however in this case paho will reconnect.
Related
I want to send notifications to my window manager on linux through the org.freedesktop.Notifications service. In d-feet this works, but in C, I get the error "Connection was disconnected before a reply was received"
#include <stdio.h>
#include <dbus/dbus.h>
int main() {
DBusError error;
DBusConnection *conn;
dbus_uint32_t serial = 0;
char *app_name = "My App";
dbus_uint32_t replaces_id = 0;
char *app_icon = "";
char *summary = "Notification from My App";
char *body = "This is a test notification from My App.";
char **actions = NULL;
dbus_int32_t timeout = -1;
dbus_uint32_t notification_id = 0;
dbus_error_init(&error);
conn = dbus_bus_get(DBUS_BUS_SESSION, &error);
if (dbus_error_is_set(&error)) {
fprintf(stderr, "Error connecting to the D-Bus session bus: %s\n", error.message);
dbus_error_free(&error);
return 1;
}
DBusMessage *message = dbus_message_new_method_call("org.freedesktop.Notifications",
"/org/freedesktop/Notifications",
"org.freedesktop.Notifications",
"Notify");
DBusMessageIter args, array;
dbus_message_iter_init_append(message, &args);
dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &app_name);
dbus_message_iter_append_basic(&args, DBUS_TYPE_UINT32, ¬ification_id);
dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &app_icon);
dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &summary);
dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &body);
dbus_message_iter_open_container(&args, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING_AS_STRING, &array);
dbus_message_iter_close_container(&args, &array);
DBusMessageIter dict_entry;
const char *key = "";
dbus_uint32_t value = 0;
dbus_message_iter_open_container(&args, DBUS_TYPE_DICT_ENTRY, NULL, &dict_entry);
dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING, &key);
DBusMessageIter variant;
dbus_message_iter_open_container(&dict_entry, DBUS_TYPE_VARIANT, DBUS_TYPE_UINT32_AS_STRING, &variant);
dbus_message_iter_append_basic(&variant, DBUS_TYPE_UINT32, &value);
dbus_message_iter_close_container(&dict_entry, &variant);
dbus_message_iter_close_container(&args, &dict_entry);
dbus_message_iter_append_basic(&args, DBUS_TYPE_INT32, &timeout);
DBusPendingCall* pending;
dbus_connection_send_with_reply(conn, message, &pending, DBUS_TIMEOUT_INFINITE);
dbus_connection_flush(conn);
dbus_message_unref(message);
dbus_pending_call_block(pending);
message = dbus_pending_call_steal_reply(pending);
dbus_pending_call_unref(pending);
DBusMessageIter args2;
int arg, id;
if(!dbus_message_iter_init(message, &args2))
fprintf(stderr, "message has no arugments!\n");
else if (DBUS_TYPE_UINT32 != (arg=dbus_message_iter_get_arg_type(&args2))) {
fprintf(stderr, "Argument is not int!\n");
switch(arg){
case DBUS_TYPE_STRING:
char *string;
dbus_message_iter_get_basic(&args2, &string);
fprintf(stderr, "ITS A STRING: %s\n", string);
break;
}}
else {
dbus_message_iter_get_basic(&args2, &id);
printf("ID: %d\n", id);
}
dbus_message_unref(message);
dbus_connection_close(conn);
return 0;
}
Edit: I fixed the segfaults, but now I get a even more obsucure reply from dbus when reading the reply arguments
While this doesn’t directly answer your question, it will help in the long run: You probably don’t want to use dbus-glib or libdbus to connect to D-Bus. Both are old and have poor API designs which make them hard to use. Using a D-Bus binding with a better-designed API will make your code easier to write and maintain in the long run.
See this answer for a comparison of the D-Bus bindings available to you which are easier to use. It is unfortunately quite confusing that there are so many bindings and that some of them are not recommended.
I want to read a sqlite3 db file for sending data from an embedded device over a data connection via mqtt to an mqtt broker in c language.
i m getting error "Failed to connect, return code 5"
can anyone please help me out for correcting this code
thanks in advance
#include <stdlib.h>
#include <string.h>
#include <MQTTClient.h>
#include <sqlite3.h>
#define ADDRESS "tcp:localhost:1883"
#define CLIENTID "......"
#define USERNAME "....."
#define PASSWORD "....."
#define TOPIC "..."
#define QOS 1
#define TIMEOUT 10000L
static int callback(void *NotUsed, int argc, char* argv[],char **azColName)
{
int i;
for(i = 0; i<argc; i++) {
printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
}
}
int main() {
int rc;
MQTTClient client;
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
MQTTClient_message pubmsg = MQTTClient_message_initializer;
MQTTClient_deliveryToken token;
MQTTClient_create(&client, ADDRESS, CLIENTID,
MQTTCLIENT_PERSISTENCE_NONE, NULL);
conn_opts.username = USERNAME;
conn_opts.password = PASSWORD;
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1;
if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to connect, return code %d\n", rc);
exit(EXIT_FAILURE);
}
pubmsg.qos = QOS;
pubmsg.retained = 0;
sqlite3 *db;
char *zErrMsg = 0;
char *sql;
const char* data = "Callback function called";
rc = sqlite3_open("db/dht.db", &db);
sql = "SELECT * from table";
rc = sqlite3_exec(db, sql, callback, (void*)data, &zErrMsg);
MQTTClient_publishMessage(client, TOPIC, &pubmsg, &token);
printf("Waiting for up to %d seconds for publication of %s\n"
"on topic %s for client with ClientID: \n",
(int)(TIMEOUT/1000), TOPIC, CLIENTID);
rc = MQTTClient_waitForCompletion(client, token, TIMEOUT);
printf("Message with delivery token %d delivered\n", token);
sqlite3_close(db);
return 0 ;
}
From the Paho C doc
MQTTClient_connect()
int MQTTClient_connect(MQTTClient handle, MQTTClient_connectOptions* options)
This function attempts to connect a previously-created client (see
MQTTClient_create()) to an MQTT server using the specified options. If
you want to enable asynchronous message and status notifications, you
must call MQTTClient_setCallbacks() prior to MQTTClient_connect().
Parameters
handle A valid client handle from a successful call to MQTTClient_create().
options A pointer to a valid MQTTClient_connectOptions structure.
Returns
MQTTCLIENT_SUCCESS if the client successfully connects to the server.
An error code is returned if the client was unable to connect to the
server. Error codes greater than 0 are returned by the MQTT protocol:
1: Connection refused: Unacceptable protocol version
2: Connection refused: Identifier rejected
3: Connection refused: Server unavailable
4: Connection refused: Bad user name or password
5: Connection refused: Not authorized
6-255: Reserved for future use
A return code of 5 means "Not authorized", this implies your username/password are wrong.
int mqtt_connection()
{
mqtt_broker_handle_t *broker = mqtt_connect(client_name, ip_addr, port);
if(broker == 0) {
printf("Connection failed, Please check the IP and port of broker\n");
return 0;
}
else {
printf("Connection established successfully\n");
}
return 1;
}
int publish_mqtt()
{
char msg[128] = "Test 2";
if(mqtt_publish(broker, topic1, msg, QoS1) == -1)
{
printf("publish failed\n");
}
else {
printf("Sent messages\n");
}
return(0);
}
I am getting error while building using scons as
master.c: In function 'publish_mqtt':
master.c:39:17: error: 'broker' undeclared (first use in this function)
if(mqtt_publish(broker, topic1, msg, QoS1) == -1)
^
master.c:39:17: note: each undeclared identifier is reported only once for each function it appears in
scons: *** [master.o] Error 1
scons: building terminated because of errors.
How to exchange the value of broker between two functions?. Is there any other way to implement this?
How to exchange the value of broker between two functions?. Is there any other way to implement this?.
Change the signatures of both functions.
Change the first function to return broker.
Change the second function to expect broker as an argument.
mqtt_broker_handle_t* mqtt_connection()
{
mqtt_broker_handle_t *broker = mqtt_connect(client_name, ip_addr, port);
if(broker == 0)
{
printf("Connection failed, Please check the IP and port of broker\n");
return NULL;
}
else
{
printf("Connection established successfully\n");
return broker;
}
}
int publish_mqtt(mqtt_broker_handle_t* broker)
{
char msg[128] = "Test 2";
if(mqtt_publish(broker, topic1, msg, QoS1) == -1)
{
printf("publish failed\n");
}
else
{
printf("Sent messages\n");
}
return(0);
}
Change the calling function.
mqtt_broker_handle_t* broker = mqtt_connection();
publish_mqtt(broker);
The problem lies in the fact broker is not available in the publish_mqtt function due to variable scoping.
Ie: Once the end brace of mqtt_connection is hit, broker no longer exists.
int mqtt_connection()
{
mqtt_broker_handle_t *broker = mqtt_connect(client_name, ip_addr, port);
...
}
If you wish to use it within publish_mqtt you need to shift the scope of the variable to be one that covers both functions. Ie:
mqtt_broker_handle_t *broker = NULL;
int mqtt_connection()
{
broker = mqtt_connect(client_name, ip_addr, port);
...
}
int publish_mqtt()
{
...
}
I'm new to the TI LaunchPad cc3200 programming. Therefore I'm playing around with the MQTT "HelloWiFi" examples from the Energia IDE, I altered the example code just a little bit. But if I run the code my publishing stops after 10 messages. If I paste my shortened loop code (just one message instead of 3) in the example code the publishing goes on and on. Why? Any ideas?
#define MQTTCLIENT_QOS2 1
#include <SPI.h>
#include <WiFi.h>
#include <WifiIPStack.h>
#include <Countdown.h>
#include <MQTTClient.h>
// your network name also called SSID
char ssid[] = "Tele*****";
// your network password
char password[] = "8757******";
char printbuf[100];
int arrivedcount = 0;
void messageArrived(MQTT::MessageData& md)
{
MQTT::Message &message = md.message;
sprintf(printbuf, "Message %d arrived: qos %d, retained %d, dup %d, packetid %d\n",
++arrivedcount, message.qos, message.retained, message.dup, message.id);
Serial.print(printbuf);
sprintf(printbuf, "Payload %s\n", (char*)message.payload);
Serial.print(printbuf);
}
WifiIPStack ipstack;
MQTT::Client<WifiIPStack, Countdown> client = MQTT::Client<WifiIPStack, Countdown>(ipstack);
const char* topic = "wireless-networks";
void connect()
{
char hostname[] = "iot.eclipse.org";
int port = 1883;
sprintf(printbuf, "Connecting to %s:%d\n", hostname, port);
Serial.print(printbuf);
int rc = ipstack.connect(hostname, port);
if (rc != 1)
{
sprintf(printbuf, "rc from TCP connect is %d\n", rc);
Serial.print(printbuf);
}
Serial.println("MQTT connecting");
MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
data.MQTTVersion = 3;
data.clientID.cstring = (char*)"DrahtloseNetzwerk";
rc = client.connect(data);
if (rc != 0)
{
sprintf(printbuf, "rc from MQTT connect is %d\n", rc);
Serial.print(printbuf);
}
Serial.println("MQTT connected");
rc = client.subscribe(topic, MQTT::QOS2, messageArrived);
if (rc != 0)
{
sprintf(printbuf, "rc from MQTT subscribe is %d\n", rc);
Serial.print(printbuf);
}
Serial.println("MQTT subscribed");
}
void setup()
{
Serial.begin(115200);
// attempt to connect to Wifi network:
Serial.print("Attempting to connect to Network named: ");
// print the network name (SSID);
Serial.println(ssid);
WiFi.begin(ssid, password);
while ( WiFi.status() != WL_CONNECTED) {
// print dots while we wait to connect
Serial.print(".");
delay(300);
}
Serial.println("\nYou're connected to the network");
Serial.println("Waiting for an ip address");
while (WiFi.localIP() == INADDR_NONE) {
// print dots while we wait for an ip addresss
Serial.print(".");
delay(300);
}
Serial.println("\nIP Address obtained");
// We are connected and have an IP address.
Serial.println(WiFi.localIP());
Serial.println("MQTT Hello example");
connect();
}
void loop()
{
if (!client.isConnected())
connect();
MQTT::Message message;
arrivedcount = 0;
// Send and receive QoS 0 message
char buf[100];
sprintf(buf, "Hello it's me s0540636!!");
message.qos = MQTT::QOS2;
message.retained = false;
message.dup = false;
message.payload = (void*)buf;
message.payloadlen = strlen(buf)+1;
int rc = client.publish(topic, message);
while (arrivedcount == 0)
client.yield(1000);
delay(1000);
}
i have a problem with my code, but it's right! But i would that when i insert an address wrong: for example http://127.0.0.1:27017/this_is_a_try my server reply me with a message "this is a try" and not with "error 404 not found". Is it so difficult? Thanks everyone help me.
#include <signal.h>
#include <stdlib.h>
#include "mongoose.h"
static int s_received_signal = 0;
static struct mg_server *s_server = NULL;
static const char *s_remote_addr = "glosbe.com:80";
static void signal_handler(int sig_num) {
signal(sig_num, signal_handler);
s_received_signal = sig_num;
}
static int ev_handler(struct mg_connection *conn, enum mg_event ev) {
struct mg_connection *client, *orig;
switch (ev) {
case MG_AUTH:
return MG_TRUE;
case MG_CONNECT:
// Send request to the remote host.
// TODO(lsm): handle connect error here.
mg_printf(conn, "GET %s HTTP/1.0\r\nHost: %s\r\n\r\n",
"/gapi/translate?from=eng&dest=fra&format=json&phrase=cat",
s_remote_addr);
return MG_TRUE;
case MG_REPLY:
// Send reply to the original connection
orig = (struct mg_connection *) conn->connection_param;
mg_send_header(orig, "Content-Type", "text/plain");
mg_send_data(orig, conn->content, conn->content_len);
mg_send_data(orig, "", 0); // Last chunk: mark the end of reply
// Disconnect connections
orig->connection_param = NULL;
conn->connection_param = NULL;
return MG_TRUE;
case MG_REQUEST:
if ((client = mg_connect(s_server, s_remote_addr)) != NULL) {
// Interconnect requests
client->connection_param = conn;
conn->connection_param = client;
return MG_MORE;
} else {
mg_printf_data(conn, "%s", "cannot send API request");
return MG_TRUE;
}
default:
return MG_FALSE;
}
}
int main(void) {
s_server = mg_create_server(NULL, ev_handler);
mg_set_option(s_server, "listening_port", "27017");
// Setup signal handlers
signal(SIGTERM, signal_handler);
signal(SIGINT, signal_handler);
printf("Listening on port %s\n", mg_get_option(s_server, "listening_port"));
while (s_received_signal == 0) {
mg_poll_server(s_server, 1000);
}
mg_destroy_server(&s_server);
printf("Existing on signal %d\n", s_received_signal);
return EXIT_SUCCESS;
}
Your codes seems very close to mongoose http_client.c sample.
Anyway reading mongoose code, it appears that the http answer code fills uri field.
In mongoose.c parse_http_message process HTTP request and answer with the following code :
ri->request_method = skip(&buf, " ");
ri->uri = skip(&buf, " ");
ri->http_version = skip(&buf, "\r\n");
Then it give the oportunity using :
mg_send_status(orig, atoi(conn->uri)); // uri contains status response
Then the answer code will becomes something like :
case MG_REPLY:
orig = (struct mg_connection *) conn->connection_param;
mg_send_status(orig, atoi(conn->uri)); // uri contains status of the http response
mg_send_header(orig, "Content-Type", "text/plain");
mg_send_data(orig, conn->content, conn->content_len);
mg_send_data(orig, "", 0); // Last chunk: mark the end of reply
orig->connection_param = NULL;
conn->connection_param = NULL;
return MG_TRUE;
EDIT
Since this commit it is possible to access to http client answer code in a more explicit way:
mg_send_status(orig, conn->status_code);