I am using the eclipse paho mqtt c library to connect to bluemix. Have done my part on the bluemix cloud and created an IoT device and registered the same, have generated API keys. But when i try to connect to the device using the below code, my code exits with an rc state of 5.
And i see log messages on the cloud saying "Closed connection, unable to authenticate".
I have tried a lot, but rc is always 5.
Appreciate your assistance.
I am using the below code, with my organization ID, device type, space ID and authentication token (on bluemix i have created a IoT device on watson).
#include <iostream>
#include <sstream>
#include <fstream>
#include <string.h>
#include "MQTTClient.h"
#define CPU_TEMP "/sys/class/thermal/thermal_zone0/temp"
using namespace std;
#define ADDRESS "tcp://<org_ID>.messaging.internetofthings.ibmcloud.com:1883"
#define CLIENTID "d:<org_ID>:<Device_type>:<space_ID>"
#define AUTHMETHOD "use-token-auth"
#define AUTHTOKEN "<authentication_token>"
#define TOPIC "iot-2/evt/status/fmt/json"
#define QOS 1
#define TIMEOUT 10000L
float getCPUTemperature(){
int CPUTemp;
fstream fs;
fs.open(CPU_TEMP, fstream::in);
fs >> CPUTemp;
fs.close();
return (((float)CPUTemp)/1000);
}
int main(int argc, char* argv[]) {
MQTTClient client;
MQTTClient_connectOptions opts = MQTTClient_connectOptions_initializer;
MQTTClient_message pubmsg = MQTTClient_message_initializer;
MQTTClient_deliveryToken token;
MQTTClient_create(&client, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL);
opts.keepAliveInterval = 20;
opts.cleansession = 1;
opts.username = AUTHMETHOD;
opts.password = AUTHTOKEN;
int rc;
if ((rc = MQTTClient_connect(client, &opts)) != MQTTCLIENT_SUCCESS)
{
cout<<"Failed to connect "<<rc<<endl;
return -1;
}
stringstream message;
message <<"{\"d\":{\"Temp\":"<<getCPUTemperature()<<"}}";
pubmsg.payload = (char*) message.str().c_str();
pubmsg.payloadlen = message.str().length();
pubmsg.qos = QOS;
pubmsg.retained = 0;
MQTTClient_publishMessage(client, TOPIC, &pubmsg, &token);
cout<< "Waiting for " << (int) (TIMEOUT/1000) << "seconds for pub of"<<message.str()<<"\non topic"<<TOPIC<<"for ClientID:"<<CLIENTID<<endl;
rc = MQTTClient_waitForCompletion(client, token, TIMEOUT);
cout<<"Message with token"<< (int)token<<"delivered"<<endl;
MQTTClient_disconnect(client,10000);
MQTTClient_destroy(&client);
return rc;
}
Apparently there are 2 connection types on bluemix, TLS and non TLS.
So i was accessing TLS type using my code meant for non-TLS connections.
Hence the authent
Related
I'm trying to read a MODBUS sensor via an ESP32.
I'm using the following library: https://github.com/emelianov/modbus-esp8266
I have the following code:
#include <ModbusRTU.h>
#include <SoftwareSerial.h>
SoftwareSerial modBusSerial;
ModbusRTU modbus;
#define startReg 100
#define endReg 123
uint16_t res[endReg - startReg + 1];
// Callback to monitor errors in the modbus
bool cb(Modbus::ResultCode event, uint16_t transactionId, void* data) {
if (event != Modbus::EX_SUCCESS) {
Serial.print("Request result: 0x");
Serial.print(event, HEX);
}
return true;
}
void setup() {
Serial.begin(115200); // Default serial port (Hardware serial)
modBusSerial.begin(9600, SWSERIAL_8E1, MB_RX, MB_TX); // modbus configuration SWSERIAL_8E1 = 8 bits data, even parity and 1 stop-bit
modbus.begin(&modBusSerial);
modbus.master();
Serial.println("starting modbus...");
while (true) {
Serial.println(modBusSerial.read());
res[endReg - startReg] = 0; // string terminator to allow to use res as char*
if (!modbus.slave()) {
modbus.readIreg(16, startReg, res, endReg - startReg, cb);
}
modbus.task();
Serial.print("result: ");
Serial.println((char*) res);
delay(1000); // every second
}
}
Response I get;
When I do the exact same in QModMaster, I do get the correct output. Anyone any idea what I'm doing wrong here?
These are the settings I use;
I am aware of the "wrong" address in my code. I have 2 identical sensors but one is connected to my computer while the other one is connected to my ESP32.
Thanks in advance!
I've taken this code almost directly from the dns-sd SDK sample, and yet, it does not find the services I search for.
There is no error, just none of the callbacks are called. This is linked against the Apple Bonjour SDK on Windows 10 x32.
If I run "dns-sd -B _http._tcp" it finds many instances!
void DNSSD_API IterateServiceInstances(DNSServiceRef sdRef,
DNSServiceFlags flags,
uint32_t interfaceIndex,
DNSServiceErrorType errorCode,
const char * serviceName,
const char * regtype,
const char * replyDomain,
void * context)
{
puts("IterateServiceInstances is never called!");
}
void DiscoverSegments()
{
printf("Discovering Segments...");
DNSServiceRef client = NULL;
DNSServiceErrorType err;
err = DNSServiceBrowse(&client,
0,
0,
"_http._tcp",
"",
IterateServiceInstances,
NULL);
if (kDNSServiceErr_NoError != err)
printf("Error: Unable to enumerate Bonjour to find devices.\n");
int main(int argc, char ** argv)
{
DiscoverSegments();
}
Because your socket message loop must keep track of ALL of the socket handles (client service refs) and pump them all while open...
I am wondering whether it is possible to reliably connect a TCP socket to itself -- that is, to get just one socket where whatever you send() on you receive back through recv(). I saw that this can happen (e.g., here, here, and here), but none of these posts explain how to do this programmatically and reliably (i.e., this is usually touted as a curiosity, rather than a feature one would use deliberately). I'm interested in a solution for Windows, Mac, and Linux.
Just for completeness, please let me explain why I'm interested in this. I'm writing a cloud-based application where servers can send messages to other servers, including themselves. Each server uses one socket to talk to other servers, and so, to unify the code and make certain threading issues simpler, it would be good if the server could talk to itself using just one socket as well.
EDIT: #Rufflewind suggested connecting to the loopback adapter. I tried that using the code below, both with and without the call to listen. In all cases, however, I got an error (either "Invalid argument" or "Operation not supported"). What am I doing wrong?
#include <iostream>
#include <netinet/tcp.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
void die(const char* const message) {
perror(message);
exit(0);
}
#define CHECK(operation,message) \
if ((operation) != 0) \
die(message)
int main(int argc, char* argv[]) {
sockaddr_in local;
local.sin_family = AF_INET;
local.sin_port = htons(40000);
inet_aton("127.0.0.1", &local.sin_addr);
int sck = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
CHECK(bind(sck, (struct sockaddr *)&local, sizeof(local)), "Error while binding the socket to an address");
// CHECK(listen(sck, 1), "Error while listening.");
CHECK(connect(sck, (struct sockaddr *)&local, sizeof(local)), "Error while connecting the socket to self");
std::cout << "Succeeded in connecting sockets!" << std::endl;
const char* message = "ABCDEFGH";
const size_t messageLength = ::strlen(message) + 1;
const char* currentSend = message;
ssize_t leftToSend = messageLength;
while (leftToSend != 0) {
const ssize_t sent = send(sck, currentSend, leftToSend, 0);
if (sent == -1)
die("Can't send.");
currentSend += sent;
leftToSend -= sent;
}
std::cout << "Sent the message!" << std::endl;
char buffer[256];
char* currentRead = buffer;
size_t leftToRead = messageLength;
while (leftToRead != 0) {
const ssize_t read = recv(sck, currentRead, leftToRead, 0);
if (read == -1)
die("Can't read.");
currentRead += read;
leftToRead -= read;
}
std::cout << "Received message: " << buffer << std::endl;
return 0;
}
The most straightforward approach would be to bind to the loopback adapter. Just listen to 127.0.0.1 on some arbitrary port and the connect to that.
The problem with this approach is that the port is global on the machine, so that means other programs can connect to it too, and if you have multiple programs you might run into conflicts or conceivably exhaust all the possible ports.
Another approach is to use Unix domain sockets, but this is not supported on Windows.
I have a device that listen to UDP packets on port IN_PORT and echo the message on port OUT_PORT. I can communicate with it using a test software like Packet Sender.
I have to write a C++ library (Win32 at the moment) to communicate with the device. I made several tests but I still wasn't able to communicate. My guess is to use this workflow:
create socket
fill sockaddr_in structure with the device address, AF_INET family and the listeng port (OUT_PORT)
bind the socket
change sockaddr_in.sin_port with IN_PORT and send a packet (using sendto)
wait for an answer (using recvfrom)
repeat from 4
This works if I simulate the device with the Packet Sender utility working locally (device address = 127.0.0.1). I can't use the same workflow to connect to a remote address, even in the same subnet (e.g. my PC address: 192.168.1.2, remote PC address 192.168.1.5), since I get WSAEADDRNOTAVAIL error.
I've tested several different workflows, and read several discussions on the topic here and there, but none works, awfully.
Can someone give me some hints on the subject.
Thanks!
MIX
Your work flow is slightly wrong. It should be more like this instead:
create socket
fill sockaddr_in structure with the address of the local network adapter that is communicating with the device, AF_INET family, and the listenig port (OUT_PORT)
bind the socket
change sockaddr.sin_addr with device address, and sockaddr_in.sin_port with IN_PORT, and send a packet (using sendto)
wait for an answer (using recvfrom)
repeat from 4
I changed my code following Remy Lebeau hints. It works now. If someone will like to have a look and spot some weak points, or suggest improvements, I'll be glad (a code that "just works" is never enough; it must also "shine"!). Comments mark the previous (wrong) version of the code.
#pragma comment (lib, "Ws2_32.lib")
#include <winsock2.h>
#include <stdlib.h>
#include <stdio.h>
#include <STRING>
#define IN_PORT 18
#define OUT_PORT 17
#define LOCAL_IP "10.0.10.108"
#define DEVICE_IP "10.0.10.104"
#define DEFAULT_BUFLEN 1024
int main(int argc, char *argv[])
{
WSADATA wsaData;
SOCKET sck;
struct sockaddr_in sckAddrInfo;
bool terminate;
char dataBuffer[DEFAULT_BUFLEN];
int rcvDataLength;
int sckAddrInfoLength;
WSAStartup(MAKEWORD(2,2), &wsaData);
sck = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
memset((&sckAddrInfo), 0, sizeof(sckAddrInfo));
sckAddrInfo.sin_family = AF_INET;
sckAddrInfo.sin_port = htons(IN_PORT);
//sckAddrInfo.sin_addr.s_addr = inet_addr(DEVICE_IP); // WRONG! Must bind local address
sckAddrInfo.sin_addr.s_addr = inet_addr(LOCAL_IP);
bind(sck, (struct sockaddr*)(&sckAddrInfo), sizeof(sckAddrInfo));
terminate = false;
sckAddrInfoLength = sizeof(sckAddrInfo);
while(!terminate)
{
printf("Write echo request: ");
gets(dataBuffer);
sckAddrInfo.sin_addr.s_addr = inet_addr(DEVICE_IP); // Must set device address, too, not just output port
sckAddrInfo.sin_port = htons(OUT_PORT);
sendto(sck, dataBuffer, strlen(dataBuffer), 0, (struct sockaddr*)(&sckAddrInfo), sizeof(sckAddrInfo));
memset(dataBuffer, '\0', DEFAULT_BUFLEN);
rcvDataLength = recvfrom(sck, dataBuffer, DEFAULT_BUFLEN, 0, (struct sockaddr*)(&sckAddrInfo), &sckAddrInfoLength);
printf("Device answer: %s\n", dataBuffer);
if(strcmp(dataBuffer, "quit") == 0)
terminate = true;
}
closesocket(sck);
WSACleanup();
return 0;
}
How to have gwan send no reply to some requests, i.e. make a servlet closed silently without building and sending a reply?
It is useful to reduce the out-going bandwidth from the server side.
For collecting data only, there's no need to respond anything to the client.
You can also close the connection from the servlet by doing something like (untested):
#include <sys/socket.h>
char buf[1024];
int s = (int)get_env(argv, CLIENT_SOCKET);
shutdown(s, SHUT_WR);
while(read(s, buf, sizeof(buf)) > 0);
close(s);
return 500;
Then return something like 500 like above so you don't have to build a reply.
You can do that with a gwan connection handler.
I think this is the event that you need to catch on the handler. Since you want the servlet to run then close the connection after.
HDL_BEFORE_WRITE, // after a reply was built, but before it is sent
Here is a sample code for the connection handler. You still need to add your filter. This code will close all requests after the reply was built.
int init(int argc, char *argv[])
{
u32 *states = (u32*)get_env(argv, US_HANDLER_STATES);
*states = (1 << HDL_BEFORE_WRITE)
}
int main(int argc, char *argv[])
{
long state = (long)argv[0];
if(state == HDL_BEFORE_WRITE)
{
return 0; // Close connection
}
return(255); // continue G-WAN's default execution path
}