inital commit
This commit is contained in:
		
						commit
						0df4ec2435
					
				
							
								
								
									
										7
									
								
								VersionInfo.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								VersionInfo.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | ||||
| #ifndef VERSIONINFO_H | ||||
| #define VERSIONINFO_H | ||||
| 
 | ||||
| #define BUILD_TIMESTAMP "2022-10-16T18:54:22Z" | ||||
| #define CLIENT_VERSION  "" | ||||
| 
 | ||||
| #endif /* VERSIONINFO_H */ | ||||
							
								
								
									
										6
									
								
								compile.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										6
									
								
								compile.sh
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,6 @@ | ||||
| #!/bin/bash | ||||
| 
 | ||||
| gcc src/main.c src/mqtt.c src/gpio.c \ | ||||
| 	-lpthread -lpaho-mqtt3a -lbcm2835 \ | ||||
| 	-o relayClient \ | ||||
| 	-I src | ||||
							
								
								
									
										
											BIN
										
									
								
								relayClient
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								relayClient
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										26
									
								
								relayClient.service
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								relayClient.service
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,26 @@ | ||||
| # systemd service file to start relayClient | ||||
| 
 | ||||
| [Unit] | ||||
| Description=MQTT client for switching relays | ||||
| #After=network.target | ||||
| After=mosquitto.service | ||||
| 
 | ||||
| [Service] | ||||
| Type=simple | ||||
| # Run as normal pi user - change to the user name you wish to run relayClient | ||||
| User=mreenen | ||||
| Group=mreenen | ||||
| WorkingDirectory=/home/mreenen/relayClient | ||||
| 
 | ||||
| ExecStart=/home/mreenen/relayClient/relayClient | ||||
| # Use SIGINT to stop | ||||
| KillSignal=SIGINT | ||||
| # Auto restart on crash | ||||
| Restart=on-failure | ||||
| RestartSec=20 | ||||
| # Tag things in the log | ||||
| SyslogIdentifier=relayClient | ||||
| #StandardOutput=syslog | ||||
| 
 | ||||
| [Install] | ||||
| WantedBy=multi-user.target | ||||
							
								
								
									
										19
									
								
								src/conf.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/conf.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | ||||
| #if !defined(CONF_H) | ||||
| #define CONF_H | ||||
| 
 | ||||
| #define ADDRESS     "tcp://test.mosquitto.org:1883"
 | ||||
| #define CLIENTID    "relayClient" | ||||
| #define TOPIC       "coolhaven/relayClient" | ||||
| #define PAYLOAD     "relay1=on" | ||||
| #define QOS         1 | ||||
| #define TIMEOUT     10000L | ||||
| 
 | ||||
| #define RECON_TIMEOUT 60 | ||||
| 
 | ||||
| #if defined(_WIN32) | ||||
|   #define SLEEP(n) Sleep(n*10) | ||||
| #else | ||||
|   #define SLEEP(n) usleep(n * 1000L) | ||||
| #endif | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										26
									
								
								src/gpio.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/gpio.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,26 @@ | ||||
| // const uint LED_PIN = PICO_DEFAULT_LED_PIN;
 | ||||
| // gpio_init(LED_PIN);
 | ||||
| // gpio_set_dir(LED_PIN, GPIO_OUT);
 | ||||
| // while (true) {
 | ||||
| //     gpio_put(LED_PIN, 1);
 | ||||
| //     sleep_ms(250);
 | ||||
| //     gpio_put(LED_PIN, 0);
 | ||||
| //     sleep_ms(250);
 | ||||
| // }
 | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include <bcm2835.h> | ||||
| 
 | ||||
| 
 | ||||
| void gpio_init(unsigned int p){ | ||||
|   bcm2835_init(); | ||||
| } | ||||
| 
 | ||||
| void gpio_set_dir(unsigned int gpio, int out){ | ||||
|   printf("DEBUG: set gpio pin %d to an %s\n", gpio, (out) ? "output" : "input"); | ||||
|   bcm2835_gpio_fsel(gpio, (out) ? BCM2835_GPIO_FSEL_OUTP : BCM2835_GPIO_FSEL_INPT); | ||||
| } | ||||
| 
 | ||||
| void gpio_put(unsigned int gpio, int value){ | ||||
|   bcm2835_gpio_write(gpio, (value) ? HIGH : LOW); | ||||
| } | ||||
							
								
								
									
										5
									
								
								src/gpio.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/gpio.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | ||||
| 
 | ||||
| 
 | ||||
| void gpio_init(unsigned int p); | ||||
| void gpio_set_dir(unsigned int gpio, int out); | ||||
| void gpio_put(unsigned int gpio, int value); | ||||
							
								
								
									
										126
									
								
								src/main.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										126
									
								
								src/main.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,126 @@ | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| 
 | ||||
| #include "conf.h" | ||||
| 
 | ||||
| #include "MQTTAsync.h" | ||||
| #include "mqtt.h" | ||||
| #include "gpio.h" | ||||
| 
 | ||||
| //  4: relay displays
 | ||||
| // 17: led strip
 | ||||
| // 22: relay2
 | ||||
| // 27: relay3
 | ||||
| 
 | ||||
| void onConnect(void* context){ | ||||
|   MQTT_subscribe("coolhaven/relayClient", 1); | ||||
| } | ||||
| 
 | ||||
| const int gpio_pin[] = {4, 17, 22, 27, -1, -1, -1, -1, -1, -1}; | ||||
| typedef enum action_e {TURN_ON, TURN_OFF, TOGGLE} action_t; | ||||
| void action(int relay, action_t acct){ | ||||
|   if(gpio_pin[relay] == -1){ | ||||
|     printf("WARING: invalid relay number"); | ||||
|     return; | ||||
|   } | ||||
|   switch (acct) { | ||||
|     case TURN_ON: | ||||
|       printf("ACTION: turn relay%d on\n", relay); | ||||
|       gpio_put(gpio_pin[relay], 0); | ||||
|       break; | ||||
|     case TURN_OFF: | ||||
|       printf("ACTION: turn relay%d off\n", relay); | ||||
|       gpio_put(gpio_pin[relay], 1); | ||||
|       break; | ||||
|     case TOGGLE: | ||||
|       // printf("ACTION: Toggle relay%d\n", relay);
 | ||||
|       printf("WARNING: Toogle not suported yet\n"); | ||||
|       break; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void relayClient(MQTTAsync_message* message){ | ||||
|   //message->payloadlen, (char*)message->payload
 | ||||
|   if(message->payloadlen < 6){ | ||||
|     printf("ERROR: playload to short\n"); | ||||
|     return; | ||||
|   } | ||||
|   if(!strncmp(message->payload, "relay", 5)){ | ||||
|     printf("ERROR: invalid playload\n"); | ||||
|     return; | ||||
|   } | ||||
|   char relay = *((char*)(message->payload + 5)); | ||||
|   if(relay < '0' && relay > '9'){ | ||||
|     printf("ERROR: invalid playload\n"); | ||||
|     return; | ||||
|   } | ||||
|   relay -= '0'; | ||||
|   if(message->payloadlen == 6){ | ||||
|     action(relay, TOGGLE); | ||||
|     return; | ||||
|   } | ||||
|   if(*((char*)(message->payload + 6)) != '='){ | ||||
|     printf("ERROR: invalid playload\n"); | ||||
|     return; | ||||
|   } | ||||
|   if(message->payloadlen == 9 && strncmp(message->payload + 6, "on", 2)){ | ||||
|     action(relay, TURN_ON); | ||||
|     return; | ||||
|   } | ||||
|   if(message->payloadlen == 10 && strncmp(message->payload + 6, "off", 3)){ | ||||
|     action(relay, TURN_OFF); | ||||
|     return; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void onMessage(char* topicName, int topicLen, MQTTAsync_message* message){ | ||||
|   char* topic = "coolhaven/relayClient"; | ||||
|   char result = 1; | ||||
|   for (int i = 0; i < topicLen && i < strlen(topic); i++) { | ||||
|     if(*(topicName+i) != *(topic+i)){ | ||||
|       result = 0; | ||||
|       printf("topic corect until char %d\n", i); | ||||
|       break; | ||||
|     } | ||||
|   } | ||||
|   if(result){ | ||||
|     relayClient(message); | ||||
|     return; | ||||
|   } | ||||
|   // if(strncmp(topicName, "coolhaven/relayClient", topicLen)){
 | ||||
|   //   relayClient(message);
 | ||||
|   //   return;
 | ||||
|   // }
 | ||||
|   printf("invlid topic (%.*s; %d)\n", topicLen, topicName, topicLen); | ||||
|   return; | ||||
| } | ||||
| 
 | ||||
| int main(int argc, char* argv[]){ | ||||
|   printf("==============================\n" | ||||
|          "=== relayClient ==============\n" | ||||
|          "==============================\n\n"); | ||||
| 
 | ||||
|   gpio_init(5); | ||||
|   for(int i=0; i<10; i++){ | ||||
|     if(gpio_pin[i] == 0) | ||||
|       continue; | ||||
|     gpio_set_dir(gpio_pin[i], 1); | ||||
|   } | ||||
| 
 | ||||
|   clientConf_t* client = MQTT_connect(&onConnect, &onMessage); | ||||
|   if(client == NULL){ | ||||
|     return -1; | ||||
|   } | ||||
| 
 | ||||
|   char ch = 0; | ||||
| 	while(ch != 'Q' && ch != 'q'){ | ||||
| 		ch = getchar(); | ||||
|     switch (ch) { | ||||
|       case 'q': | ||||
|       case 'Q': | ||||
|         MQTT_disconnect(client); | ||||
|         return 0; | ||||
|     } | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										162
									
								
								src/mqtt.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										162
									
								
								src/mqtt.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,162 @@ | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <time.h> | ||||
| 
 | ||||
| #include "conf.h" | ||||
| 
 | ||||
| #include "MQTTAsync.h" | ||||
| #include "mqtt.h" | ||||
| 
 | ||||
| clientConf_t* client; | ||||
| 
 | ||||
| void reconnect(){ | ||||
|   int rc; | ||||
| 
 | ||||
|   if(client->last_reconn.t + RECON_TIMEOUT > time(NULL)){ | ||||
|     if(client->last_reconn.c < 10){ | ||||
|       printf("Wait %d seconds until reconect. reconect counter on %d\n", RECON_TIMEOUT, client->last_reconn.c); | ||||
|       SLEEP(RECON_TIMEOUT); | ||||
|     } else { | ||||
|       printf("Wait one hour until reconect. reconect counter on %d\n", client->last_reconn.c); | ||||
|       SLEEP(3600); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
| 	printf("Reconnecting to MQTT server\n"); | ||||
|   rc = MQTTAsync_connect(client->client, &(client->conn_opts)); | ||||
| 	if (rc != MQTTASYNC_SUCCESS){ | ||||
| 		printf("ERROR: Failed to reconnect, return code %d\n", rc); | ||||
|     client->last_reconn.t = time(NULL); | ||||
|     client->last_reconn.c++; | ||||
| 	} else { | ||||
|     client->last_reconn.c = 0; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void connlost(void *context, char *cause){ | ||||
| 	printf("\nERROR: Lost connection to MQTT\n"); | ||||
| 	if(cause){ | ||||
| 		printf("     cause: %s\n", cause); | ||||
|   } | ||||
| 
 | ||||
|   reconnect(); | ||||
| } | ||||
| 
 | ||||
| int msgarrvd(void *context, char *topicName, int topicLen, MQTTAsync_message *message){ | ||||
|   printf("Message arrived\n"); | ||||
|   printf("     topic: %s\n", topicName); | ||||
|   printf("   message: %.*s\n", message->payloadlen, (char*)message->payload); | ||||
| 
 | ||||
|   (*(client->onMessage))(topicName, topicLen, message); | ||||
| 
 | ||||
|   MQTTAsync_freeMessage(&message); | ||||
|   MQTTAsync_free(topicName); | ||||
|   return 1; | ||||
| } | ||||
| 
 | ||||
| void onConnectFailure(void* context, MQTTAsync_failureData* response){ | ||||
| 	printf("Connect failed, rc %d\n", response->code); | ||||
|   reconnect(); | ||||
| } | ||||
| 
 | ||||
| void onConn(void* context, MQTTAsync_successData* response){ | ||||
| 	printf("connected to MQTT server\n"); | ||||
|   (*(client->onConnect))(client); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| clientConf_t* MQTT_connect(void (*onConnect_cb)(void* context), void (*onMessage)(char* topicName, int topicLen, MQTTAsync_message* message)){ | ||||
|   client = (clientConf_t*) malloc(sizeof(clientConf_t)); // keep this util i say so
 | ||||
| 	int rc; | ||||
| 	int ch; | ||||
| 
 | ||||
|   rc = MQTTAsync_create(&(client->client), ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL); | ||||
| 	if (rc != MQTTASYNC_SUCCESS){ | ||||
| 		printf("Failed to create client, return code %d\n", rc); | ||||
|     free(client); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 
 | ||||
|   client->onMessage = onMessage; | ||||
|   client->onConnect = onConnect_cb; | ||||
|   client->last_reconn.c = 0; | ||||
|   client->last_reconn.t = 0; | ||||
| 
 | ||||
|   rc = MQTTAsync_setCallbacks(client->client, client, &connlost, &msgarrvd, NULL); | ||||
| 	if (rc != MQTTASYNC_SUCCESS){ | ||||
| 		printf("Failed to set callbacks, return code %d\n", rc); | ||||
|   	MQTTAsync_destroy(&(client->client)); | ||||
|     free(client); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 
 | ||||
|   MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer; | ||||
|   client->conn_opts = conn_opts; | ||||
| 	client->conn_opts.keepAliveInterval = 20; | ||||
| 	client->conn_opts.cleansession = 1; | ||||
| 	client->conn_opts.onSuccess = onConn; | ||||
| 	client->conn_opts.onFailure = onConnectFailure; | ||||
| 	client->conn_opts.context = &client; | ||||
|   printf("connecting to MQTT server (%s)\n", ADDRESS); | ||||
|   rc = MQTTAsync_connect(client->client, &(client->conn_opts)); | ||||
| 	if(rc != MQTTASYNC_SUCCESS){ | ||||
| 		printf("Failed to start connect, return code %d\n", rc); | ||||
|   	MQTTAsync_destroy(&(client->client)); | ||||
|     free(client); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 
 | ||||
|   return client; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| void onDisconnectFailure(void* context, MQTTAsync_failureData* response){ | ||||
| 	printf("Faild to discontect from MQTT, rc %d\n", response->code); | ||||
|   MQTTAsync_destroy(client->client); | ||||
|   free(client); | ||||
| } | ||||
| 
 | ||||
| void onDisconnect(void* context, MQTTAsync_successData* response){ | ||||
| 	printf("disconnected from MQTT server\n"); | ||||
|   MQTTAsync_destroy(client->client); | ||||
|   free(client); | ||||
| } | ||||
| 
 | ||||
| void MQTT_disconnect(){ | ||||
|   int rc; | ||||
|   MQTTAsync_disconnectOptions disc_opts = MQTTAsync_disconnectOptions_initializer; | ||||
| 	disc_opts.onSuccess = &onDisconnect; | ||||
| 	disc_opts.onFailure = &onDisconnectFailure; | ||||
|   rc = MQTTAsync_disconnect(client->client, &disc_opts); | ||||
| 	if (rc != MQTTASYNC_SUCCESS){ | ||||
| 		printf("Failed to start disconnect, return code %d\n", rc); | ||||
|   	MQTTAsync_destroy(client->client); | ||||
| 		return; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| void onSubscribe(void* context, MQTTAsync_successData* response){ | ||||
|   // printf("Successful subscribed to %s\n", (char*) context);
 | ||||
| 	printf("Successful subscribed\n"); | ||||
| } | ||||
| 
 | ||||
| void onSubscribeFailure(void* context, MQTTAsync_failureData* response){ | ||||
| 	printf("ERROR: Subscribe failed, rc %d\n", response->code); | ||||
| } | ||||
| 
 | ||||
| void MQTT_subscribe(char* topic, int qos){ | ||||
| 	int rc; | ||||
| 
 | ||||
| 	printf("Subscribing to topic %s (QoS%d)\n", topic, qos); | ||||
| 	MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer; | ||||
| 	opts.onSuccess = &onSubscribe; | ||||
| 	opts.onFailure = &onSubscribeFailure; | ||||
|   opts.context = topic; | ||||
|   rc = MQTTAsync_subscribe(client->client, topic, qos, &opts); | ||||
| 	if (rc != MQTTASYNC_SUCCESS){ | ||||
| 		printf("ERROR: Failed to start subscribe, return code %d\n", rc); | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										24
									
								
								src/mqtt.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/mqtt.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| #if !defined(MQTT_H) | ||||
| #define MQTT_H | ||||
| 
 | ||||
| #include <time.h> | ||||
| #include "MQTTAsync.h" | ||||
| 
 | ||||
| typedef struct clientConf_s { | ||||
|   MQTTAsync client; | ||||
|   MQTTAsync_connectOptions conn_opts; | ||||
|   struct lastReconn_s { | ||||
|     int c; | ||||
|     time_t t; | ||||
|   } last_reconn; | ||||
|   void (*onConnect)(void* context); | ||||
|   void (*onMessage)(char* topicName, int topicLen, MQTTAsync_message* message); | ||||
| } clientConf_t; | ||||
| 
 | ||||
| 
 | ||||
| clientConf_t* MQTT_connect(void (*onConnect)(void* context), void (*onMessage)(char* topicName, int topicLen, MQTTAsync_message* message)); | ||||
| void MQTT_disconnect(); | ||||
| 
 | ||||
| void MQTT_subscribe(char* topic, int qos); | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										35
									
								
								src/test.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								src/test.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,35 @@ | ||||
| // A simple C program to demonstrate callback
 | ||||
| #include <stdio.h> | ||||
| 
 | ||||
| #include "mqtt.h" | ||||
| 
 | ||||
| 
 | ||||
| typedef struct data_s { | ||||
|   int num; | ||||
|   void (*cb)(int num); | ||||
| } data_t; | ||||
| 
 | ||||
| void a(void* context){ | ||||
|   int num = ((clientConf_t*)context)->last_reconn.c; | ||||
|   printf("Hi, this is a. you gave me the number %d\n", num); | ||||
| } | ||||
| 
 | ||||
| clientConf_t b(int num, void* cb){ | ||||
|   clientConf_t data; | ||||
|   data.last_reconn.c = num; | ||||
|   data.onConnect = cb; | ||||
|   return data; | ||||
| } | ||||
| 
 | ||||
| void fire(clientConf_t* data){ | ||||
|   (*(data->onConnect))(data); | ||||
| } | ||||
| 
 | ||||
| int main(){ | ||||
|   printf("callback test\n"); | ||||
| 
 | ||||
|   clientConf_t d = b(5, &a); | ||||
| 
 | ||||
|   fire(&d); | ||||
| 
 | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user