· 6 years ago · Nov 28, 2019, 10:34 PM
1#include <PubSubClient.h>
2#include <ESP8266WiFi.h>
3#include <Servo.h>
4#define ANGLE_FIELD 0
5#define DATA_FIELD 1 // Data field to post the signal strength to.
6
7
8
9
10
11char ssid[] = "chameleon"; // Change this to your network SSID (name).
12char pass[] = "Dr.House123"; // Change this to your network password.
13const char* server = "mqtt.thingspeak.com";
14char mqttUserName[] = "dasperg"; // Use any name.
15char mqttPass[] = "7Y6ALYQUEXNMVDGD"; // Change to your MQTT API key from Account > MyProfile.
16long readChannelID=924420;
17char readAPIKey[]="UBDV7ZDTB6P4NIYJ";
18long writeChannelID=924420;
19char writeAPIKey[] = "LMSUYGP3JPH1IRB2";
20
21WiFiClient client; // Initialize the Wi-Fi client library.
22PubSubClient mqttClient( client ); // Initialize the PuBSubClient library.
23Servo myservo; // Create servo object to control a servo .
24
25int fieldsToPublish[8]={1,1,0,0,0,0,0,0}; // Change to allow multiple fields.
26float dataToPublish[8]; // Holds your field data.
27int changeFlag=0; // Let the main loop know ther is new data to set.
28int servo_pos=0; // Servo position
29
30
31
32
33
34
35//
36// Prototypes
37//
38
39// Handle messages from MQTT subscription.
40int mqttSubscriptionCallback(char* topic, byte* payload, unsigned int length);
41
42// Generate a unique client ID and connect to MQTT broker.
43void mqttConnect();
44
45// Subscribe to a field or feed from a ThingSpeak channel.
46int mqttSubscribe( long subChannelID,int field,char* readKey, int unSub);
47
48// Publish messages to a channel feed.
49void mqttPublish(long pubChannelID, char* pubWriteAPIKey, float dataArray[], int fieldArray[]);
50
51// Connect to a given Wi-Fi SSID
52int connectWifi();
53
54// Measure the Wi-Fi signal strength.
55void updateRSSIValue();
56
57// Build a random client ID for MQTT connection.
58void getID(char clientID[], int idLength);
59
60
61
62
63
64
65/**
66 * Process messages received from subscribed channel via MQTT broker.
67 * topic - Subscription topic for message.
68 * payload - Field to subscribe to. Value 0 means subscribe to all fields.
69 * mesLength - Message length.
70 */
71
72int mqttSubscriptionCallback( char* topic, byte* payload, unsigned int mesLength ) {
73
74 char p[mesLength + 1];
75 memcpy( p, payload, mesLength );
76 p[mesLength] = NULL;
77 Serial.print( "Answer: " );
78 Serial.println( String(p) );
79}
80
81
82
83void mqttConnect()
84{
85 char clientID[ 9 ];
86
87 // Loop until connected.
88 while ( !mqttClient.connected() )
89 {
90
91 getID(clientID,8);
92
93 // Connect to the MQTT broker.
94 Serial.print( "Attempting MQTT connection..." );
95 if ( mqttClient.connect( clientID, mqttUserName, mqttPass ) )
96 {
97 Serial.println( "Connected with Client ID: " + String( clientID ) + " User "+ String( mqttUserName ) + " Pwd "+String( mqttPass ) );
98
99 } else
100 {
101 Serial.print( "failed, rc = " );
102 // See https://pubsubclient.knolleary.net/api.html#state for the failure code explanation.
103 Serial.print( mqttClient.state() );
104 Serial.println( " Will try again in 5 seconds" );
105 delay( 5000 );
106 }
107 }
108}
109
110
111
112
113
114/**
115 * Build a random client ID.
116 * clientID - Character array for output
117 * idLength - Length of clientID (actual length is one character longer for NULL)
118 */
119
120void getID(char clientID[], int idLength){
121static const char alphanum[] ="0123456789"
122"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
123"abcdefghijklmnopqrstuvwxyz"; // For random generation of the client ID.
124
125 // Generate client ID.
126 for (int i = 0; i < idLength ; i++) {
127 clientID[ i ] = alphanum[ random( 51 ) ];
128 }
129 clientID[ idLength ] = '\0';
130
131}
132
133
134
135
136/**
137 * Subscribe to fields of a channel.
138 * subChannelID - Channel to subscribe to.
139 * field - Field to subscribe to. Value 0 means subscribe to all fields.
140 * readKey - Read API key for the subscribe channel.
141 * unSub - Set to 1 for unsubscribe.
142 */
143
144int mqttSubscribe( long subChannelID, int field, char* readKey, int unsubSub ){
145 String myTopic;
146
147 // There is no field zero, so if field 0 is sent to subscribe to, then subscribe to the whole channel feed.
148 if (field==0){
149 myTopic="channels/"+String( subChannelID )+"/subscribe/json/"+String( readKey );
150 }
151 else{
152 myTopic="channels/"+String( subChannelID )+"/subscribe/fields/field"+String( field )+"/"+String( readKey );
153 }
154
155 Serial.println( "Subscribing to " +myTopic );
156 Serial.println( "State= " + String( mqttClient.state() ) );
157
158 return mqttClient.subscribe( myTopic.c_str() ,0 );
159}
160
161
162
163
164/**
165 * Publish to a channel
166 * pubChannelID - Channel to publish to.
167 * pubWriteAPIKey - Write API key for the channel to publish to.
168 * dataArray - Binary array indicating which fields to publish to, starting with field 1.
169 * fieldArray - Array of values to publish, starting with field 1.
170 */
171
172void mqttPublish(long pubChannelID, char* pubWriteAPIKey, float dataArray[], int fieldArray[]) {
173 int index=0;
174 String dataString="";
175
176 updateRSSIValue(); // Make sure the stored value is updated.
177
178 //
179 while (index<8){
180
181 // Look at the field array to build the posting string to send to ThingSpeak.
182 if (fieldArray[ index ]>0){
183
184 dataString+="&field" + String( index+1 ) + "="+String( dataArray [ index ] );
185 }
186 index++;
187 }
188
189 Serial.println( dataString );
190
191 // Create a topic string and publish data to ThingSpeak channel feed.
192 String topicString ="channels/" + String( pubChannelID ) + "/publish/"+String( pubWriteAPIKey );
193 mqttClient.publish( topicString.c_str(), dataString.c_str() );
194 Serial.println( "Published to channel " + String( pubChannelID ) );
195}
196
197
198int connectWifi()
199{
200 delay(10);
201 // We start by connecting to a WiFi network
202 Serial.println();
203 Serial.print("Connecting to ");
204 Serial.println(ssid);
205
206 WiFi.begin(ssid, pass);
207
208 while (WiFi.status() != WL_CONNECTED) {
209 delay(500);
210 Serial.print(".");
211 }
212
213 randomSeed(micros());
214
215 Serial.println("");
216 Serial.println("WiFi connected");
217 Serial.println("IP address: ");
218 Serial.println(WiFi.localIP());
219// while ( WiFi.status() != WL_CONNECTED ) {
220// WiFi.begin( ssid, pass );
221// delay( 2500 );
222// Serial.println( "Connecting to Wi-Fi" );
223// }
224// Serial.println( "Connected" );
225
226}
227
228
229void updateRSSIValue(){
230
231 long rssi = WiFi.RSSI();
232 Serial.print( "RSSI:" );
233 Serial.println(rssi);
234 dataToPublish[ DATA_FIELD ]=float( rssi );
235
236}
237
238
239
240
241
242void setup() {
243 Serial.begin( 115200 );
244 Serial.println( "Start" );
245 int status = WL_IDLE_STATUS; // Set temporary Wi-Fi status.
246
247 connectWifi(); // Connect to Wi-Fi network.
248 mqttClient.setServer( server, 1883 ); // Set the MQTT broker details.
249 mqttClient.setCallback( mqttSubscriptionCallback ); // Set the MQTT message handler function.
250 Serial.println("Setup finished");
251}
252
253void loop() {
254 if (WiFi.status() != WL_CONNECTED) {
255 connectWifi();
256 }
257
258 if (!mqttClient.connected())
259 {
260
261 mqttConnect(); // Connect if MQTT client is not connected.
262
263 if(mqttSubscribe( readChannelID,1,readAPIKey,0 )==1 ){
264 Serial.println( " Subscribed " );
265 }
266 }
267
268 mqttClient.loop(); // Call the loop to maintain connection to the server.
269
270 if ((servo_pos>175)||(servo_pos<0)){
271 servo_pos=0;
272 }
273
274 if (changeFlag){
275
276 changeFlag=0;
277 myservo.write(servo_pos);
278 dataToPublish[ANGLE_FIELD]=servo_pos;
279 delay(1100); // Wait for ThingSpeak to publish.
280 Serial.println( "Servo value " + String( servo_pos ) );
281 mqttPublish( writeChannelID, writeAPIKey, dataToPublish, fieldsToPublish );
282 }
283
284 delay(1);
285
286}