I have built a MQTT client on an ESP8266-01 which gathers sensor data and publishes it to my account dashboard on Adafruit.com. I also built one on an ESP8266-12e which subscribes to my Adafruit account and turns on a pin when certain conditions exist on one of the dashboard values.
I am trying to use the tutorial here (https://stablekernel.com/article/esp8266-programming-building-a-iot-weather-station-episode-3/#comments-area) to create an iPhone app that will subscribe to the Adafruit dashboard and display various values as well as publish one value when a button is tapped. I have installed the frameworks using Pods and copied/modified the code, but when I launch the app it doesn't update the values and it doesn't publish the values when the button is tapped.
Here is my code for the iPhone app:
#import "ViewController.h"
#import <MQTTClient/MQTTClient.h>
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UILabel *batteryValueLabel;
@property (strong, nonatomic) IBOutlet UILabel *tempValueLabel;
@property (weak, nonatomic) IBOutlet UILabel *levelValueLabel;
@property (weak, nonatomic) IBOutlet UILabel *tripValueLabel;
@property (weak, nonatomic) IBOutlet UILabel *dateValueLabel;
@property(nonatomic, strong, readwrite) NSArray *certificates;
@property(nonatomic, weak) IBOutlet UIButton *Fill;
-(IBAction)Turnon:(id)sender;
@end
NSString *trip = @"0";
int trigger =1;
MQTTSession *session;
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
MQTTCFSocketTransport *transport = [[MQTTCFSocketTransport alloc] init];
transport.host = @"io.adafruit.com";
transport.port = 1883;
transport.certificates = [NSArray arrayWithObjects:@"xxxxxx",@"axxxxxxxxxxxxxxxxxxxx", nil];
session = [[MQTTSession alloc] init];
session.transport = transport;
session.delegate = self;
[session connectAndWaitTimeout:30];
[session subscribeToTopic:@"feeds/date" atLevel:1 subscribeHandler:^(NSError *error, NSArray *gQoss){
//These never get called
if (error) {
NSLog(@"Subscription failed %@", error.localizedDescription);
} else {
NSLog(@"Subscription sucessfull! Granted Qos: %@", gQoss);
}
}];
}
- (void)newMessage:(MQTTSession *)session
data:(NSData *)data
onTopic:(NSString *)topic
qos:(MQTTQosLevel)qos
retained:(BOOL)retained
mid:(unsigned int)mid {
NSString *dataString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
//These don't get called
NSLog(@"%@", topic);
NSLog(@"%@", dataString);
if ([topic isEqualToString:@"feeds/date"]){
self.dateValueLabel.text = dataString;}
}
-(IBAction)Turnon:(id)sender;{
if(trigger ==1){
trip = @"0";
trigger = 2;
}
else if(trigger==2){
trip = @"100";
trigger = 1;
}
NSData* data = [trip dataUsingEncoding:NSUTF8StringEncoding];
[session publishData:data onTopic:@"feeds/trip" retain:NO qos:1 publishHandler:nil];
NSLog(@"%@", trip);
NSLog(@"%d",trigger);
}
@end
This is the log when I open the app and it tries to subscribe:
2020-12-24 17:00:47.705408-0700 iphoneMQTT[26045:13918734] [MQTTSession] init
2020-12-24 17:00:47.705578-0700 iphoneMQTT[26045:13918734] [MQTTSession] connecting
2020-12-24 17:00:47.705610-0700 iphoneMQTT[26045:13918734] [MQTTCoreDataPersistence] deleteAllFlowsForClientId MQTTClient705518
2020-12-24 17:00:47.725848-0700 iphoneMQTT[26045:13918734] [MQTTPersistence] Persistent store: /var/mobile/Containers/Data/Application/78971181-5902-4962-AED0-F954C3304BB2/Documents/MQTTClient
2020-12-24 17:00:47.727835-0700 iphoneMQTT[26045:13918734] [MQTTCFSocketTransport] open
2020-12-24 17:00:47.729945-0700 iphoneMQTT[26045:13918734] [MQTTCFSocketEncoder] setState 0/0
2020-12-24 17:00:47.780073-0700 iphoneMQTT[26045:13918734] [MQTTSessionSynchron] waiting for connect
2020-12-24 17:00:47.881014-0700 iphoneMQTT[26045:13918734] [MQTTSessionSynchron] waiting for connect
2020-12-24 17:00:47.944259-0700 iphoneMQTT[26045:13918734] [MQTTCFSocketDecoder] NSStreamEventOpenCompleted
2020-12-24 17:00:47.944465-0700 iphoneMQTT[26045:13918734] [MQTTCFSocketEncoder] NSStreamEventOpenCompleted
2020-12-24 17:00:47.944588-0700 iphoneMQTT[26045:13918734] [MQTTCFSocketEncoder] NSStreamEventHasSpaceAvailable
2020-12-24 17:00:47.944705-0700 iphoneMQTT[26045:13918734] [MQTTCFSocketEncoder] setState 0/1
2020-12-24 17:00:47.944833-0700 iphoneMQTT[26045:13918734] [MQTTSession] mqttTransportDidOpen
2020-12-24 17:00:47.944941-0700 iphoneMQTT[26045:13918734] [MQTTSession] sending CONNECT
2020-12-24 17:00:47.945760-0700 iphoneMQTT[26045:13918734] [MQTTMessage] wireFormat(30)={length = 30, bytes = 0x101c0004 4d515454 0402003c 00104d51 ... 6e743730 35353138 }...
2020-12-24 17:00:47.945955-0700 iphoneMQTT[26045:13918734] [MQTTSession] mqttTransport send
2020-12-24 17:00:47.946190-0700 iphoneMQTT[26045:13918734] [MQTTCFSocketEncoder] buffer to write (30)={length = 30, bytes = 0x101c0004 4d515454 0402003c 00104d51 ... 6e743730 35353138 }...
2020-12-24 17:00:47.946604-0700 iphoneMQTT[26045:13918734] [MQTTCFSocketEncoder] NSStreamEventHasSpaceAvailable
2020-12-24 17:00:47.982035-0700 iphoneMQTT[26045:13918734] [MQTTSessionSynchron] waiting for connect
2020-12-24 17:00:48.021667-0700 iphoneMQTT[26045:13918734] [MQTTCFSocketDecoder] NSStreamEventHasBytesAvailable
2020-12-24 17:00:48.022025-0700 iphoneMQTT[26045:13918734] [MQTTCFSocketDecoder] received (4)={length = 4, bytes = 0x20020004}...
2020-12-24 17:00:48.022129-0700 iphoneMQTT[26045:13918734] [MQTTSession] mqttTransport didReceiveMessage
2020-12-24 17:00:48.022290-0700 iphoneMQTT[26045:13918734] [MQTTDecoder] #streams=1
2020-12-24 17:00:48.022538-0700 iphoneMQTT[26045:13918734] [MQTTCFSocketDecoder] NSStreamEventHasBytesAvailable
2020-12-24 17:00:48.022721-0700 iphoneMQTT[26045:13918734] [MQTTCFSocketDecoder] received (0)={length = 0, bytes = 0x}...
2020-12-24 17:00:48.022801-0700 iphoneMQTT[26045:13918734] [MQTTSession] mqttTransport didReceiveMessage
2020-12-24 17:00:48.022891-0700 iphoneMQTT[26045:13918734] [MQTTDecoder] #streams=2
2020-12-24 17:00:48.022970-0700 iphoneMQTT[26045:13918734] [MQTTCFSocketDecoder] NSStreamEventEndEncountered
2020-12-24 17:00:48.023046-0700 iphoneMQTT[26045:13918734] [MQTTSession] mqttTransport mqttTransportDidClose
2020-12-24 17:00:48.023242-0700 iphoneMQTT[26045:13918734] [MQTTSession] closeInternal
2020-12-24 17:00:48.023346-0700 iphoneMQTT[26045:13918734] [MQTTCFSocketTransport] close
2020-12-24 17:00:48.082571-0700 iphoneMQTT[26045:13918734] [MQTTSessionSynchron] end connect
2020-12-24 17:00:48.083128-0700 iphoneMQTT[26045:13918734] [MQTTSession] subscribeToTopics:{
"feeds/date" = 1;
}]
2020-12-24 17:00:48.083264-0700 iphoneMQTT[26045:13918734] nextMsgId synchronizing
2020-12-24 17:00:48.083342-0700 iphoneMQTT[26045:13918734] nextMsgId synchronized
2020-12-24 17:00:48.083422-0700 iphoneMQTT[26045:13918734] flowforClientId requestingPerform
2020-12-24 17:00:48.083512-0700 iphoneMQTT[26045:13918734] flowforClientId performing
2020-12-24 17:00:48.083802-0700 iphoneMQTT[26045:13918734] flowforClientId performed
2020-12-24 17:00:48.083897-0700 iphoneMQTT[26045:13918734] nextMsgId synchronized done
2020-12-24 17:00:48.084142-0700 iphoneMQTT[26045:13918734] [MQTTMessage] wireFormat(17)={length = 17, bytes = 0x820f0002000a66656564732f6461746502}...
2020-12-24 17:00:48.084231-0700 iphoneMQTT[26045:13918734] [MQTTSession] mqttTransport send
2020-12-24 17:00:48.084360-0700 iphoneMQTT[26045:13918734] [MQTTCFSocketEncoder] buffer to write (17)={length = 17, bytes = 0x820f0002000a66656564732f6461746502}...
2020-12-24 17:00:48.084445-0700 iphoneMQTT[26045:13918734] [MQTTCFSocketEncoder] streamError: (null)
2020-12-24 17:00:48.084520-0700 iphoneMQTT[26045:13918734] [MQTTCFSocketEncoder] setState 1/2
and this is the log when I tap the publish button:
2020-12-24 17:01:06.419897-0700 iphoneMQTT[26045:13918734] [MQTTSession] publishData:{length = 1, bytes = 0x30}... onTopic:feeds/trip retain:0 qos:1 publishHandler:0x0
2020-12-24 17:01:06.420220-0700 iphoneMQTT[26045:13918734] nextMsgId synchronizing
2020-12-24 17:01:06.420349-0700 iphoneMQTT[26045:13918734] nextMsgId synchronized
2020-12-24 17:01:06.420462-0700 iphoneMQTT[26045:13918734] flowforClientId requestingPerform
2020-12-24 17:01:06.420582-0700 iphoneMQTT[26045:13918734] flowforClientId performing
2020-12-24 17:01:06.421045-0700 iphoneMQTT[26045:13918734] flowforClientId performed
2020-12-24 17:01:06.421166-0700 iphoneMQTT[26045:13918734] nextMsgId synchronized done
2020-12-24 17:01:06.421405-0700 iphoneMQTT[26045:13918734] flowforClientId requestingPerform
2020-12-24 17:01:06.421519-0700 iphoneMQTT[26045:13918734] flowforClientId performing
2020-12-24 17:01:06.421745-0700 iphoneMQTT[26045:13918734] flowforClientId performed
2020-12-24 17:01:06.424204-0700 iphoneMQTT[26045:13918734] [MQTTPersistence] pre-sync: i1 u0 d0
2020-12-24 17:01:06.428943-0700 iphoneMQTT[26045:13918734] [MQTTPersistence] postsync: i0 u0 d0
2020-12-24 17:01:06.429125-0700 iphoneMQTT[26045:13918734] [MQTTPersistence] sizes 0/0
2020-12-24 17:01:06.429326-0700 iphoneMQTT[26045:13918734] [MQTTSession] queueing message 3
2020-12-24 17:01:06.429930-0700 iphoneMQTT[26045:13918734] 0
2020-12-24 17:01:06.430028-0700 iphoneMQTT[26045:13918734] 2
I have tried to follow the actions with the framework and main code, but I am now good enough to know why things are not working correctly.
This is the code that is used on the ESP's to subscribe and publish using Adafruit's MQTTClient frameworks and code:
#include <ESP8266WiFi.h>
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"
/************************* WiFi Access Point *********************************/
#define WLAN_SSID "xxxxxxxxxxxx
#define WLAN_PASS "xxxxxxxxxxxxxx"
/************************* Adafruit.io Setup *********************************/
#define AIO_SERVER "io.adafruit.com"
#define AIO_SERVERPORT 1883 // 8883 for MQTTS
#define AIO_USERNAME "xxxxxx"
#define AIO_KEY "xxxxxxxxxxxxxxxxxxxxxxxxxxx"
#define LED 14
int tripper = 1;
/************ Global State (you don't need to change this!) ******************/
// Create an ESP8266 WiFiClient class to connect to the MQTT server.
WiFiClient client;
// or... use WiFiFlientSecure for SSL
//WiFiClientSecure client;
// Setup the MQTT client class by passing in the WiFi client and MQTT server and login details.
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);
/****************************** Feeds ***************************************/
// Setup a feed called 'photocell' for publishing.
// Notice MQTT paths for AIO follow the form: <username>/feeds/<feedname>
Adafruit_MQTT_Publish temperature = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/temperature");
// Setup a feed called 'onoff' for subscribing to changes.
Adafruit_MQTT_Subscribe trip2 = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/trip");
/*************************** Error Reporting *********************************/
Adafruit_MQTT_Subscribe errors = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/errors");
Adafruit_MQTT_Subscribe throttle = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/throttle");
/*************************** Sketch Code ************************************/
// Bug workaround for Arduino 1.6.6, it seems to need a function declaration
// for some reason (only affects ESP8266, likely an arduino-builder bug).
void MQTT_connect();
void setup() {
Serial.begin(115200);
delay(1000);
pinMode(D5,OUTPUT);
digitalWrite(D5,LOW);
Serial.println(F("Adafruit MQTT demo"));
// Connect to WiFi access point.
Serial.println(); Serial.println();
Serial.print("Connecting to ");
Serial.println(WLAN_SSID);
WiFi.begin(WLAN_SSID, WLAN_PASS);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println();
Serial.println("WiFi connected");
Serial.println("IP address: "); Serial.println(WiFi.localIP());
// Setup MQTT subscription for onoff feed
mqtt.subscribe(&trip2);
// Setup MQTT subscriptions for throttle & error messages
mqtt.subscribe(&throttle);
mqtt.subscribe(&errors);
}
//could this be where the problem is what format the data is in (I don't think so but....
uint32_t x=80;
void loop() {
// Ensure the connection to the MQTT server is alive (this will make the first
// connection and automatically reconnect when disconnected). See the MQTT_connect
// function definition further below.
MQTT_connect();
// this is our 'wait for incoming subscription packets' busy subloop
// try to spend your time here
//12e
Adafruit_MQTT_Subscribe *subscription;
while ((subscription = mqtt.readSubscription(5000))) {
if (subscription == &trip2) {
Serial.print(F("Got onoff: "));
Serial.println((char *)trip2.lastread);
uint16_t sliderval = atoi((char *)trip2.lastread);
if((sliderval ==0)&&(tripper == 1)){
digitalWrite(D5,HIGH);
delay(2000);
digitalWrite(D5,LOW);
tripper = 2;
}
else if(sliderval == 50){
}
else if((sliderval == 100)&&(tripper == 2)){
digitalWrite(D5,HIGH);
delay(2000);
digitalWrite(D5,LOW);
tripper = 1;
}
} else if(subscription == &errors) {
Serial.print(F("ERROR: "));
Serial.println((char *)errors.lastread);
} else if(subscription == &throttle) {
Serial.println((char *)throttle.lastread);
}
}
// Now we can publish stuff! 01
Serial.print(F("\nSending temperature val "));
Serial.print(x);
Serial.print("...");
if (! temperature.publish(x)) {
Serial.println(F("Failed"));
} else {
Serial.println(F("OK!"));
}
//delay(60000);//01
delay(5000);//12e
}
// Function to connect and reconnect as necessary to the MQTT server.
// Should be called in the loop function and it will take care if connecting.
void MQTT_connect() {
int8_t ret;
// Stop if already connected.
if (mqtt.connected()) {
return;
}
Serial.print("Connecting to MQTT... ");
uint8_t retries = 3;
while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected
Serial.println(mqtt.connectErrorString(ret));
Serial.println("Retrying MQTT connection in 5 seconds...");
mqtt.disconnect();
delay(5000); // wait 5 seconds
retries--;
if (retries == 0) {
// basically die and wait for WDT to reset me
while (1);
}
}
Serial.println("MQTT Connected!");
}
I'm sorry if I have posted too much codes but I wanted everyone to have as much information as they need. If anyone has worked on something like this, please help.
So I got connected by adding:
session = [[MQTTSession alloc] init];
session.userName = @"xxxxxxxxx";
session.password = @"xxxxxxxxxxxxxxxxxxxxxxxxxxx";
session.transport = transport;
session.delegate = self;
[session connectWithConnectHandler:^(NSError *error) {
if(!error){
[session subscribeToTopic:@"feeds/temperature" atLevel:1 subscribeHandler:^(NSError *error, NSArray *gQoss){
if (error) {
NSLog(@"Subscription failed %@", error.localizedDescription);
} else {
NSLog(@"Subscription sucessfull! Granted Qos: %@", gQoss);
}
}];
}
else {NSLog(@"[connectWithConnectHandler]Error Connect %@", error.localizedDescription);}
}];
to my code.
However not I get an error from Adafruit
MQTT ERROR: rejected, not a valid topic format
Has anyone else had this problem. I think I will post another question with this problem. Should take less code I hope.