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