24 #include <stdlib.h> |
24 #include <stdlib.h> |
25 #include <unistd.h> |
25 #include <unistd.h> |
26 #include <getopt.h> |
26 #include <getopt.h> |
27 #include <sys/types.h> |
27 #include <sys/types.h> |
28 #include <signal.h> |
28 #include <signal.h> |
|
29 #include <string.h> |
|
30 #include <errno.h> |
|
31 |
|
32 #include <mosquitto.h> |
29 |
33 |
30 |
34 |
31 #include "main.h" |
35 #include "main.h" |
|
36 |
|
37 |
|
38 #define STATUS_CONNECTING 0 |
|
39 #define STATUS_CONNACK_RECVD 1 |
|
40 #define STATUS_WAITING 2 |
|
41 |
|
42 /* Global variables for use in callbacks. See sub_client.c for an example of |
|
43 * using a struct to hold variables for use in callbacks. */ |
|
44 static char *topic = NULL; |
|
45 //static char *message = NULL; |
|
46 //static long msglen = 0; |
|
47 static int qos = 0; |
|
48 //static int retain = 0; |
|
49 static int status = STATUS_CONNECTING; |
|
50 static int mid_sent = 0; |
|
51 static int last_mid = -1; |
|
52 static int last_mid_sent = -1; |
|
53 static bool connected = true; |
|
54 //static char *username = NULL; |
|
55 //static char *password = NULL; |
|
56 static bool disconnect_sent = false; |
|
57 static bool quiet = false; |
|
58 static bool debug = false; |
|
59 static bool shutdown = false; |
|
60 |
32 |
61 |
33 |
62 |
34 void help(void) |
63 void help(void) |
35 { |
64 { |
36 fprintf(stdout, "Usage: thermomeneters [-d] [-h]\n"); |
65 fprintf(stdout, "Usage: thermomeneters [-d] [-h]\n"); |
41 |
70 |
42 |
71 |
43 void die(int onsig) |
72 void die(int onsig) |
44 { |
73 { |
45 switch (onsig) { |
74 switch (onsig) { |
46 case SIGHUP: fprintf(stdout, "[main] Hangup detected"); |
75 case SIGHUP: fprintf(stdout, "[main] Hangup detected\n"); |
47 break; |
76 break; |
48 case SIGINT: fprintf(stdout, "[main] Interrupt from keyboard"); |
77 case SIGINT: fprintf(stdout, "[main] Interrupt from keyboard\n"); |
49 break; |
78 break; |
50 case SIGTERM: fprintf(stdout, "[main] Termination signal received"); |
79 case SIGTERM: fprintf(stdout, "[main] Termination signal received\n"); |
51 break; |
80 break; |
52 default: fprintf(stdout, "[main] die on signal %d", onsig); |
81 default: fprintf(stdout, "[main] die on signal %d\n", onsig); |
53 } |
82 } |
54 |
83 |
55 exit(onsig); |
84 shutdown = true; |
|
85 } |
|
86 |
|
87 |
|
88 |
|
89 void my_connect_callback(struct mosquitto *mosq, void *obj, int result) |
|
90 { |
|
91 int rc = MOSQ_ERR_SUCCESS; |
|
92 |
|
93 fprintf(stdout, (char *)"my_connect_callback result=%d\n", result); |
|
94 if (!result) { |
|
95 status = STATUS_CONNACK_RECVD; |
|
96 } else { |
|
97 fprintf(stderr, "%s\n", mosquitto_connack_string(result)); |
|
98 } |
|
99 } |
|
100 |
|
101 |
|
102 |
|
103 void my_disconnect_callback(struct mosquitto *mosq, void *obj, int rc) |
|
104 { |
|
105 fprintf(stdout, (char *)"my_disconnect_callback\n"); |
|
106 connected = false; |
|
107 } |
|
108 |
|
109 |
|
110 |
|
111 void my_publish_callback(struct mosquitto *mosq, void *obj, int mid) |
|
112 { |
|
113 fprintf(stdout, (char *)"my_publish_callback mid=%d\n", mid); |
|
114 |
|
115 last_mid_sent = mid; |
|
116 // if(mode == MSGMODE_STDIN_LINE){ |
|
117 // if(mid == last_mid){ |
|
118 // mosquitto_disconnect(mosq); |
|
119 // disconnect_sent = true; |
|
120 // } |
|
121 // }else if(disconnect_sent == false){ |
|
122 // mosquitto_disconnect(mosq); |
|
123 // disconnect_sent = true; |
|
124 // } |
|
125 } |
|
126 |
|
127 |
|
128 |
|
129 void my_log_callback(struct mosquitto *mosq, void *obj, int level, const char *str) |
|
130 { |
|
131 printf("%s\n", str); |
56 } |
132 } |
57 |
133 |
58 |
134 |
59 |
135 |
60 int main(int argc, char *argv[]) |
136 int main(int argc, char *argv[]) |
61 { |
137 { |
62 int i, c; |
138 int i, c, len, rc, rc2; |
|
139 char *id = NULL; |
|
140 char *host = (char *)"lx02.mbse.ym"; |
|
141 int port = 1883; |
|
142 struct mosquitto *mosq = NULL; |
|
143 char hostname[256], buf[1024]; |
|
144 int keepalive = 60; |
|
145 unsigned int max_inflight = 20; |
|
146 char err[1024]; |
63 |
147 |
64 while (1) { |
148 while (1) { |
65 int option_index = 0; |
149 int option_index = 0; |
66 static struct option long_options[] = { |
150 static struct option long_options[] = { |
67 {"debug", 0, 0, 'c'}, |
151 {"debug", 0, 0, 'c'}, |
89 for (i = 0; i < NSIG; i++) { |
173 for (i = 0; i < NSIG; i++) { |
90 if ((i != SIGCHLD) && (i != SIGKILL) && (i != SIGSTOP)) |
174 if ((i != SIGCHLD) && (i != SIGKILL) && (i != SIGSTOP)) |
91 signal(i, (void (*))die); |
175 signal(i, (void (*))die); |
92 } |
176 } |
93 |
177 |
94 |
178 /* |
|
179 * Initialize mosquitto communication |
|
180 */ |
|
181 mosquitto_lib_init(); |
|
182 hostname[0] = '\0'; |
|
183 gethostname(hostname, 256); |
|
184 hostname[255] = '\0'; |
|
185 len = strlen("thermometers/") + 1 + strlen(hostname); |
|
186 id = malloc(len); |
|
187 if(!id) { |
|
188 if (!quiet) |
|
189 fprintf(stderr, "Error: Out of memory.\n"); |
|
190 mosquitto_lib_cleanup(); |
|
191 return 1; |
|
192 } |
|
193 snprintf(id, len, "thermometers/%s", hostname); |
|
194 if(strlen(id) > MOSQ_MQTT_ID_MAX_LENGTH) { |
|
195 /* |
|
196 * Enforce maximum client id length of 23 characters |
|
197 */ |
|
198 id[MOSQ_MQTT_ID_MAX_LENGTH] = '\0'; |
|
199 } |
|
200 |
|
201 fprintf(stdout, "id: %s\n", id); |
|
202 |
|
203 mosq = mosquitto_new(id, true, NULL); |
|
204 if(!mosq) { |
|
205 switch(errno) { |
|
206 case ENOMEM: |
|
207 if (!quiet) |
|
208 fprintf(stderr, "Error: Out of memory.\n"); |
|
209 break; |
|
210 case EINVAL: |
|
211 if (!quiet) |
|
212 fprintf(stderr, "Error: Invalid id.\n"); |
|
213 break; |
|
214 } |
|
215 mosquitto_lib_cleanup(); |
|
216 return 1; |
|
217 } |
|
218 |
|
219 if(debug) { |
|
220 mosquitto_log_callback_set(mosq, my_log_callback); |
|
221 } |
|
222 |
|
223 /* |
|
224 * Set our will |
|
225 */ |
|
226 topic = malloc(28 + strlen(hostname)); |
|
227 sprintf(topic, "clients/%s/thermometers/state", hostname); |
|
228 sprintf(buf, "0"); |
|
229 rc = mosquitto_will_set(mosq, topic, strlen(buf), buf, qos, true); |
|
230 if (rc) { |
|
231 if (rc == MOSQ_ERR_INVAL) { |
|
232 fprintf(stderr, "Input parameters invalid\n"); |
|
233 } else if (rc == MOSQ_ERR_NOMEM) { |
|
234 fprintf(stderr, "Out of Memory\n"); |
|
235 } else if (rc == MOSQ_ERR_PAYLOAD_SIZE) { |
|
236 fprintf(stderr, "Invalid payload size\n"); |
|
237 } |
|
238 mosquitto_lib_cleanup(); |
|
239 return rc; |
|
240 } |
|
241 |
|
242 mosquitto_max_inflight_messages_set(mosq, max_inflight); |
|
243 mosquitto_connect_callback_set(mosq, my_connect_callback); |
|
244 mosquitto_disconnect_callback_set(mosq, my_disconnect_callback); |
|
245 mosquitto_publish_callback_set(mosq, my_publish_callback); |
|
246 |
|
247 rc = mosquitto_connect(mosq, host, port, keepalive); |
|
248 if (rc) { |
|
249 if (rc == MOSQ_ERR_ERRNO) { |
|
250 strerror_r(errno, err, 1024); |
|
251 fprintf(stderr, "Error: %s\n", err); |
|
252 } else { |
|
253 fprintf(stderr, "Unable to connect (%d).\n", rc); |
|
254 } |
|
255 mosquitto_lib_cleanup(); |
|
256 return rc; |
|
257 } |
|
258 |
|
259 /* |
|
260 * Initialise is complete, report our presence state |
|
261 */ |
|
262 mosquitto_loop_start(mosq); |
|
263 |
|
264 // topic = malloc(28 + strlen(hostname)); |
|
265 sprintf(topic, "clients/%s/thermometers/state", hostname); |
|
266 sprintf(buf, "1"); |
|
267 rc2 = mosquitto_publish(mosq, &mid_sent, topic, strlen(buf), buf, qos, 1); |
|
268 free(topic); |
|
269 |
|
270 |
|
271 fprintf(stdout, (char *)"Enter loop, connected %d\n", connected); |
|
272 do { |
|
273 if (status == STATUS_CONNACK_RECVD) { |
|
274 // fprintf(stdout, (char *)"Ok\n"); |
|
275 // if(fgets(buf, 1024, stdin)){ |
|
276 // buf[strlen(buf)-1] = '\0'; |
|
277 // rc2 = mosquitto_publish(mosq, &mid_sent, topic, strlen(buf), buf, qos, retain); |
|
278 // if(rc2){ |
|
279 // if(!quiet) fprintf(stderr, "Error: Publish returned %d, disconnecting.\n", rc2); |
|
280 // mosquitto_disconnect(mosq); |
|
281 // } |
|
282 // } else |
|
283 if (shutdown) { |
|
284 fprintf(stdout, (char *)"Shutdown\n"); |
|
285 topic = malloc(28 + strlen(hostname)); |
|
286 sprintf(topic, "clients/%s/thermometers/state", hostname); |
|
287 sprintf(buf, "0"); |
|
288 rc2 = mosquitto_publish(mosq, &mid_sent, topic, strlen(buf), buf, qos, true); |
|
289 free(topic); |
|
290 last_mid = mid_sent; |
|
291 status = STATUS_WAITING; |
|
292 } |
|
293 } else if (status == STATUS_WAITING) { |
|
294 fprintf(stdout, (char *)"Waiting\n"); |
|
295 if (last_mid_sent == last_mid && disconnect_sent == false) { |
|
296 mosquitto_disconnect(mosq); |
|
297 disconnect_sent = true; |
|
298 } |
|
299 usleep(100000); |
|
300 } |
|
301 rc = MOSQ_ERR_SUCCESS; |
|
302 |
|
303 } while(rc == MOSQ_ERR_SUCCESS && connected); |
|
304 fprintf(stdout, (char *)"Out of loop\n"); |
|
305 |
|
306 mosquitto_loop_stop(mosq, false); |
|
307 |
|
308 mosquitto_destroy(mosq); |
|
309 mosquitto_lib_cleanup(); |
|
310 |
|
311 fprintf(stdout, (char *)"Bye Bye\n"); |
95 return 0; |
312 return 0; |
96 } |
313 } |
97 |
314 |