seems like it works

This commit is contained in:
Edward Emelianov 2024-06-17 15:10:51 +03:00
parent fdc3a6ec1c
commit 5d5e7c4a46
7 changed files with 92 additions and 68 deletions

View File

@ -69,7 +69,7 @@ static void readssl(SSL *ssl){
if(bytes > 0){
buf[bytes] = 0;
verbose(1, "Received: \"%s\"", buf);
handle_message(buf, client_out_gpios);
if(!G.commands) handle_message(buf, client_out_gpios); // don't react on incoming messages if just send commands
}else if(bytes < 0){
LOGWARN("Server disconnected or other error");
ERRX("Disconnected");
@ -114,7 +114,7 @@ void clientproc(SSL_CTX *ctx, int fd){
}
while(1){
#ifdef __arm__
poll_gpio(&ssl, 1, client_in_gpios);
poll_gpio(&ssl, -1, client_in_gpios);
#endif
readssl(ssl);
}

View File

@ -39,7 +39,10 @@ static const int gpio_inputs[GPIO_IN_NUMBER] = {18, 23, 24, 25, 8, 7};
static const int gpio_outputs[GPIO_OUT_NUMBER] = {17, 27, 22, 10, 9, 11};
// last time GPIO was activated
static double gpio_set_time[GPIO_OUT_NUMBER] = {-1., -1., -1., -1., -1., -1.};
static double gpio_clear_time[GPIO_OUT_NUMBER] = {1., 1., 1., 1., 1., 1.};
// last GPIO event times & event values
static double gpio_in_time[GPIO_IN_NUMBER] = {0.};
static enum gpio_v2_line_event_id gpio_in_event_id[GPIO_IN_NUMBER] = {0};
/**
* @brief gpio_chkclr - clear outputs by timeout
@ -47,9 +50,9 @@ static double gpio_set_time[GPIO_OUT_NUMBER] = {-1., -1., -1., -1., -1., -1.};
static void gpio_chkclr(){
double tnow = dtime();
for(int i = 0; i < GPIO_OUT_NUMBER; ++i){
if(t[i] < 0.) continue;
if(tnow - t[i] < GPIO_TIMEOUT) continue;
gpio_clear_output(gpio_outputs[i]);
if(gpio_clear_time[i] < 0.) continue;
if(tnow - gpio_clear_time[i] < GPIO_TIMEOUT) continue;
gpio_set_output(gpio_outputs[i]);
}
}
@ -94,30 +97,32 @@ int gpio_setup_outputs(){
rq_out.offsets[i] = gpio_outputs[i];
snprintf(rq_out.consumer, GPIO_MAX_NAME_SIZE-1, "outputs");
rq_out.num_lines = GPIO_OUT_NUMBER;
rq_out.config.flags = GPIO_V2_LINE_FLAG_OUTPUT | GPIO_V2_LINE_FLAG_OPEN_DRAIN | GPIO_V2_LINE_FLAG_ACTIVE_LOW | GPIO_V2_LINE_FLAG_BIAS_DISABLED;
rq_out.config.flags = GPIO_V2_LINE_FLAG_OUTPUT | GPIO_V2_LINE_FLAG_BIAS_DISABLED;
rq_out.config.num_attrs = 0;
if(-1 == ioctl(gpiofd, GPIO_V2_GET_LINE_IOCTL, &rq_out)){
LOGERR("Unable setup outputs: %s", strerror(errno));
WARNX("Can't setup outputs");
return -1;
}
gpio_chkclr(); // set all outputs
DBG("Outputs are ready");
return rq_out.fd;
}
static int gpio_setreset(int input, int set){
static int gpio_setreset(int output, int set){
int idx = -1;
for(int i = 0; i < GPIO_IN_NUMBER; ++i){
if(gpio_inputs[i] == input){
for(int i = 0; i < GPIO_OUT_NUMBER; ++i){
if(gpio_outputs[i] == output){
idx = i; break;
}
}
DBG("idx = %d", idx);
if(idx < 0 || idx > GPIO_OUT_NUMBER) return FALSE;
if(set == 0 && (dtime() - gpio_clear_time[idx] < GPIO_SETTMOUT)) return FALSE; // time!
struct gpio_v2_line_values values;
bzero(&values, sizeof(values));
uint64_t val = (1<<idx) & GPIO_OUT_MASK;
values.mask = val;
values.bits = set ? 0 : val; // invert bit due to GPIO_V2_LINE_FLAG_ACTIVE_LOW
values.bits = set ? val : 0;
DBG("mask=%" PRIu64 ", val=%" PRIu64, values.mask, values.bits);
if(-1 == ioctl(rq_out.fd, GPIO_V2_LINE_SET_VALUES_IOCTL, &values)){
LOGERR("Unable to change GPIO values (mask=%" PRIu64 ", val=%" PRIu64 ": %s", values.mask, values.bits, strerror(errno));
@ -125,8 +130,8 @@ static int gpio_setreset(int input, int set){
return FALSE;
}
// change last event time
if(set) gpio_set_time[idx] = 0;
else gpio_set_time[idx] = dtime();
if(set == 0) gpio_clear_time[idx] = dtime();
else gpio_clear_time[idx] = -1.;
return TRUE;
}
@ -135,16 +140,18 @@ static int gpio_setreset(int input, int set){
* @param input - number of input pin
* @return true if all OK, false if failed
*/
int gpio_set_output(int input){
return gpio_setreset(input, 1);
int gpio_set_output(int output){
DBG("GPIO SET");
return gpio_setreset(output, 1);
}
/**
* @brief gpio_clear_output - clear to 0 output pin
* @param input - number of input pin
* @return true if all OK, false if failed
*/
int gpio_clear_output(int input){
return gpio_setreset(input, 0);
int gpio_clear_output(int output){
DBG("GPIO CLEAR");
return gpio_setreset(output, 0);
}
@ -177,39 +184,41 @@ int gpio_poll(uint32_t *up, uint32_t *down){
if(up) *up = 0;
if(down) *down = 0;
gpio_chkclr(); // clear old outputs
do{
pfd.fd = rq_in.fd;
pfd.events = POLLIN | POLLPRI;
int p = poll(&pfd, 1, 1);
if(p == 0) break; // nothing happened
else if(p == -1){
LOGERR("poll() error: %s", strerror(errno));
WARNX("GPIO poll() error");
return -1;
}
DBG("Got GPIO event!");
int r = read(rq_in.fd, &event, sizeof(struct gpio_v2_line_event));
if(r != sizeof(struct gpio_v2_line_event)){
LOGERR("Error reading GPIO data");
WARNX("Error reading GPIO data");
return -1;
}
verbose(1, "Got event:\n\ttimestamp=%" PRIu64 "\n\tid=%d\n\toff=%d\n\tseqno=%d\n\tlineseqno=%d",
event.timestamp_ns, event.id, event.offset, event.seqno, event.line_seqno);
if(up){
if(event.id == GPIO_V2_LINE_EVENT_RISING_EDGE){
*up = event.offset;
break;
}else *up = 0;
}
if(down){
if(event.id == GPIO_V2_LINE_EVENT_FALLING_EDGE){
*down = event.offset;
break;
}else *down = 0;
}
}while(1);
return (int)event.offset;
pfd.fd = rq_in.fd;
pfd.events = POLLIN | POLLPRI;
int p = poll(&pfd, 1, 1);
if(p == 0) return 0; // nothing happened
else if(p == -1){
LOGERR("poll() error: %s", strerror(errno));
WARNX("GPIO poll() error");
return -1;
}
DBG("Got GPIO event!");
int r = read(rq_in.fd, &event, sizeof(struct gpio_v2_line_event));
if(r != sizeof(struct gpio_v2_line_event)){
LOGERR("Error reading GPIO data");
WARNX("Error reading GPIO data");
return -1;
}
int idx = event.offset;
double tnow = dtime();
// omit same events or bouncing
if(gpio_in_event_id[idx] == event.id || tnow - gpio_in_time[idx] < GPIO_DEBOUNSE_TIMEOUT) return 0;
gpio_in_event_id[idx] = event.id;
gpio_in_time[idx] = tnow;
verbose(1, "Got event:\n\ttimestamp=%" PRIu64 "\n\tid=%d\n\toff=%d\n\tseqno=%d\n\tlineseqno=%d\n\ttnow=%.3f",
event.timestamp_ns, event.id, idx, event.seqno, event.line_seqno, tnow);
if(up){
if(event.id == GPIO_V2_LINE_EVENT_RISING_EDGE){
*up = idx;
}else *up = 0;
}
if(down){
if(event.id == GPIO_V2_LINE_EVENT_FALLING_EDGE){
*down = idx;
}else *down = 0;
}
return idx;
}
void gpio_close(){

View File

@ -37,12 +37,16 @@
// timeout - clear GPIO after receiving command - 1 minute
#define GPIO_TIMEOUT (60.)
// don't allow to manage with GPIO over this time after last ON
#define GPIO_SETTMOUT (5.0)
// time for debounce (seconds)
#define GPIO_DEBOUNSE_TIMEOUT (0.5)
int gpio_open_device(const char *path);
int gpio_setup_outputs();
int gpio_setup_inputs();
int gpio_poll(uint32_t *up, uint32_t *down);
int gpio_set_output(int input);
int gpio_clear_output(int input);
int gpio_set_output(int output);
int gpio_clear_output(int output);
void gpio_close();

View File

@ -3,5 +3,7 @@
#define CLIENT
#define EBUG
#define __arm__
//#define SERVER

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 13.0.1, 2024-06-05T12:39:52. -->
<!-- Written by QtCreator 13.0.2, 2024-06-17T14:56:14. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>

View File

@ -23,10 +23,10 @@
#ifdef __arm__
#include "gpio.h"
// GPIO25 - LEDopen, 8 - LEDclose
// GPIO7 - LEDopen, 8 - LEDclose
static cmd_t server_in_gpios[] = {
{25, CMD_LED0},
{8, CMD_LED1},
{8, CMD_LED0},
{7, CMD_LED1},
{0, NULL}
};
@ -56,9 +56,10 @@ static int handle_connection(SSL *ssl){
LOGDBG("fd=%d, message=%s", sd, buf);
const char *ans = "FAIL";
#ifdef __arm__
if(strcmp(buf, CMD_OPEN) || strcmp(buf, CMD_CLOSE)){ // shut both 17/27 channels before run cmd
gpio_clear_output(17);
gpio_clear_output(27);
if(0 == strcmp(buf, CMD_OPEN) || 0 == strcmp(buf, CMD_CLOSE)){ // shut both 17/27 channels before run cmd
DBG("Got cmd %s -> 1st close all", buf);
gpio_set_output(17);
gpio_set_output(27);
usleep(100000); // wait a little
}
#endif

View File

@ -30,6 +30,7 @@
#else
#include "client.h"
#endif
#include "gpio.h"
#ifdef SERVER
static int OpenConn(int port){
@ -203,7 +204,7 @@ int read_string(SSL *ssl, char *buf, int l){
/**
* @brief poll_gpio - GPIO polling
* @param ssl - ssl array to write
* @param nfd - amount of descriptors (+1 - starting frol ssls[1])
* @param nfd - amount of descriptors (+1 - starting frol ssls[1]) for server or -1 for client
*/
void poll_gpio(SSL **ssls, int nfd, cmd_t *commands){
static double t0 = 0.;
@ -211,15 +212,22 @@ void poll_gpio(SSL **ssls, int nfd, cmd_t *commands){
char buf[64];
uint32_t up, down;
t0 = dtime();
if(gpio_poll(&up, &down) <= 0 || !up) return;
if(gpio_poll(&up, &down) <= 0 || !down) return;
DBG("DOWN=%d, nfd=%d", down, nfd);
for(cmd_t *c = commands; c->cmd; ++c){
if(c->gpio != up) continue;
DBG("Test %d - %s", c->gpio, c->cmd);
if(c->gpio != down) continue;
DBG("Got event %s", c->cmd);
sprintf(buf, "%s\n", c->cmd);
int l = strlen(buf);
if(nfd == 1){
if(!ssls) return;
if(nfd == -1){
DBG("Write to server");
if(SSL_write(ssls[0], buf, l) <= 0) WARNX("SSL write error");
}else{
DBG("Write to all %d clients", nfd-1);
for(int i = nfd-1; i > 0; --i){
DBG("ssls[%d]", i);
if(SSL_write(ssls[i], buf, l) <= 0){
WARNX("SSL write error");
}
@ -237,12 +245,12 @@ int handle_message(const char *msg, cmd_t *gpios){
int ret = FALSE;
for(cmd_t *c = gpios; c->cmd; ++c){
if(strcmp(msg, c->cmd)) continue;
DBG("set pin %d", c->gpio);
DBG("set pin %d (to 0)", c->gpio);
#ifdef __arm__
if(!gpio_set_output(pin)) LOGERR("Can't change state according to pin %d", pin);
if(!gpio_clear_output(c->gpio)) LOGERR("Can't change state according to pin %d", c->gpio);
else{
LOGMSG("%s gpio %d", act == 1 ? "Set" : "Reset", pin);
verbose(1, "%s gpio %d", act == 1 ? "Set" : "Reset", pin);
LOGMSG("RESET gpio %d", c->gpio);
verbose(1, "RESET gpio %d", c->gpio);
ret = TRUE;
}
#endif