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){ if(bytes > 0){
buf[bytes] = 0; buf[bytes] = 0;
verbose(1, "Received: \"%s\"", buf); 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){ }else if(bytes < 0){
LOGWARN("Server disconnected or other error"); LOGWARN("Server disconnected or other error");
ERRX("Disconnected"); ERRX("Disconnected");
@ -114,7 +114,7 @@ void clientproc(SSL_CTX *ctx, int fd){
} }
while(1){ while(1){
#ifdef __arm__ #ifdef __arm__
poll_gpio(&ssl, 1, client_in_gpios); poll_gpio(&ssl, -1, client_in_gpios);
#endif #endif
readssl(ssl); 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}; static const int gpio_outputs[GPIO_OUT_NUMBER] = {17, 27, 22, 10, 9, 11};
// last time GPIO was activated // 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 * @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(){ static void gpio_chkclr(){
double tnow = dtime(); double tnow = dtime();
for(int i = 0; i < GPIO_OUT_NUMBER; ++i){ for(int i = 0; i < GPIO_OUT_NUMBER; ++i){
if(t[i] < 0.) continue; if(gpio_clear_time[i] < 0.) continue;
if(tnow - t[i] < GPIO_TIMEOUT) continue; if(tnow - gpio_clear_time[i] < GPIO_TIMEOUT) continue;
gpio_clear_output(gpio_outputs[i]); gpio_set_output(gpio_outputs[i]);
} }
} }
@ -94,30 +97,32 @@ int gpio_setup_outputs(){
rq_out.offsets[i] = gpio_outputs[i]; rq_out.offsets[i] = gpio_outputs[i];
snprintf(rq_out.consumer, GPIO_MAX_NAME_SIZE-1, "outputs"); snprintf(rq_out.consumer, GPIO_MAX_NAME_SIZE-1, "outputs");
rq_out.num_lines = GPIO_OUT_NUMBER; 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; rq_out.config.num_attrs = 0;
if(-1 == ioctl(gpiofd, GPIO_V2_GET_LINE_IOCTL, &rq_out)){ if(-1 == ioctl(gpiofd, GPIO_V2_GET_LINE_IOCTL, &rq_out)){
LOGERR("Unable setup outputs: %s", strerror(errno)); LOGERR("Unable setup outputs: %s", strerror(errno));
WARNX("Can't setup outputs"); WARNX("Can't setup outputs");
return -1; return -1;
} }
gpio_chkclr(); // set all outputs
DBG("Outputs are ready");
return rq_out.fd; return rq_out.fd;
} }
static int gpio_setreset(int input, int set){ static int gpio_setreset(int output, int set){
int idx = -1; int idx = -1;
for(int i = 0; i < GPIO_IN_NUMBER; ++i){ for(int i = 0; i < GPIO_OUT_NUMBER; ++i){
if(gpio_inputs[i] == input){ if(gpio_outputs[i] == output){
idx = i; break; idx = i; break;
} }
} }
DBG("idx = %d", idx);
if(idx < 0 || idx > GPIO_OUT_NUMBER) return FALSE; 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; struct gpio_v2_line_values values;
bzero(&values, sizeof(values)); bzero(&values, sizeof(values));
uint64_t val = (1<<idx) & GPIO_OUT_MASK; uint64_t val = (1<<idx) & GPIO_OUT_MASK;
values.mask = val; 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); DBG("mask=%" PRIu64 ", val=%" PRIu64, values.mask, values.bits);
if(-1 == ioctl(rq_out.fd, GPIO_V2_LINE_SET_VALUES_IOCTL, &values)){ 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)); 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; return FALSE;
} }
// change last event time // change last event time
if(set) gpio_set_time[idx] = 0; if(set == 0) gpio_clear_time[idx] = dtime();
else gpio_set_time[idx] = dtime(); else gpio_clear_time[idx] = -1.;
return TRUE; return TRUE;
} }
@ -135,16 +140,18 @@ static int gpio_setreset(int input, int set){
* @param input - number of input pin * @param input - number of input pin
* @return true if all OK, false if failed * @return true if all OK, false if failed
*/ */
int gpio_set_output(int input){ int gpio_set_output(int output){
return gpio_setreset(input, 1); DBG("GPIO SET");
return gpio_setreset(output, 1);
} }
/** /**
* @brief gpio_clear_output - clear to 0 output pin * @brief gpio_clear_output - clear to 0 output pin
* @param input - number of input pin * @param input - number of input pin
* @return true if all OK, false if failed * @return true if all OK, false if failed
*/ */
int gpio_clear_output(int input){ int gpio_clear_output(int output){
return gpio_setreset(input, 0); 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(up) *up = 0;
if(down) *down = 0; if(down) *down = 0;
gpio_chkclr(); // clear old outputs gpio_chkclr(); // clear old outputs
do{ pfd.fd = rq_in.fd;
pfd.fd = rq_in.fd; pfd.events = POLLIN | POLLPRI;
pfd.events = POLLIN | POLLPRI; int p = poll(&pfd, 1, 1);
int p = poll(&pfd, 1, 1); if(p == 0) return 0; // nothing happened
if(p == 0) break; // nothing happened else if(p == -1){
else if(p == -1){ LOGERR("poll() error: %s", strerror(errno));
LOGERR("poll() error: %s", strerror(errno)); WARNX("GPIO poll() error");
WARNX("GPIO poll() error"); return -1;
return -1; }
} DBG("Got GPIO event!");
DBG("Got GPIO event!"); int r = read(rq_in.fd, &event, sizeof(struct gpio_v2_line_event));
int r = read(rq_in.fd, &event, sizeof(struct gpio_v2_line_event)); if(r != sizeof(struct gpio_v2_line_event)){
if(r != sizeof(struct gpio_v2_line_event)){ LOGERR("Error reading GPIO data");
LOGERR("Error reading GPIO data"); WARNX("Error reading GPIO data");
WARNX("Error reading GPIO data"); return -1;
return -1; }
} int idx = event.offset;
verbose(1, "Got event:\n\ttimestamp=%" PRIu64 "\n\tid=%d\n\toff=%d\n\tseqno=%d\n\tlineseqno=%d", double tnow = dtime();
event.timestamp_ns, event.id, event.offset, event.seqno, event.line_seqno); // omit same events or bouncing
if(up){ if(gpio_in_event_id[idx] == event.id || tnow - gpio_in_time[idx] < GPIO_DEBOUNSE_TIMEOUT) return 0;
if(event.id == GPIO_V2_LINE_EVENT_RISING_EDGE){ gpio_in_event_id[idx] = event.id;
*up = event.offset; gpio_in_time[idx] = tnow;
break; verbose(1, "Got event:\n\ttimestamp=%" PRIu64 "\n\tid=%d\n\toff=%d\n\tseqno=%d\n\tlineseqno=%d\n\ttnow=%.3f",
}else *up = 0; event.timestamp_ns, event.id, idx, event.seqno, event.line_seqno, tnow);
} if(up){
if(down){ if(event.id == GPIO_V2_LINE_EVENT_RISING_EDGE){
if(event.id == GPIO_V2_LINE_EVENT_FALLING_EDGE){ *up = idx;
*down = event.offset; }else *up = 0;
break; }
}else *down = 0; if(down){
} if(event.id == GPIO_V2_LINE_EVENT_FALLING_EDGE){
}while(1); *down = idx;
return (int)event.offset; }else *down = 0;
}
return idx;
} }
void gpio_close(){ void gpio_close(){

View File

@ -37,12 +37,16 @@
// timeout - clear GPIO after receiving command - 1 minute // timeout - clear GPIO after receiving command - 1 minute
#define GPIO_TIMEOUT (60.) #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_open_device(const char *path);
int gpio_setup_outputs(); int gpio_setup_outputs();
int gpio_setup_inputs(); int gpio_setup_inputs();
int gpio_poll(uint32_t *up, uint32_t *down); int gpio_poll(uint32_t *up, uint32_t *down);
int gpio_set_output(int input); int gpio_set_output(int output);
int gpio_clear_output(int input); int gpio_clear_output(int output);
void gpio_close(); void gpio_close();

View File

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

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject> <!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> <qtcreator>
<data> <data>
<variable>EnvironmentId</variable> <variable>EnvironmentId</variable>

View File

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

View File

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