inital commit

This commit is contained in:
MReenen 2022-10-24 22:33:02 +02:00
commit 0df4ec2435
11 changed files with 436 additions and 0 deletions

7
VersionInfo.h Normal file
View 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
View 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

Binary file not shown.

26
relayClient.service Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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);
}