update to gpio

master
shaun feakes 2018-06-21 09:58:45 -05:00
parent 42d5db40e2
commit 827eac8ecd
14 changed files with 563 additions and 127 deletions

View File

@ -10,7 +10,7 @@ else
WPI_LIB := -D USE_WIRINGPI -lwiringPi
endif
LIBS := $(WPI_LIB) -lm
LIBS := $(WPI_LIB) -lm -lpthread
#LIBS := -lpthread -lwiringPi -lwiringPiDev -lm
#LIBS := -lpthread -lwebsockets

View File

@ -107,26 +107,32 @@ Create a device for each piece of pool equiptment you have, eg Filter Pump, Spa
```
http://sprinklerd.ip.address:port?type=option&option=24hdelay&state=off
```
```
* // Info options
* ?type=firstload // JSON status Include cal schedule
* ?type=read // JSON status no need to include cal schedule
<host>?type=firstload // JSON status Include cal schedule
<host>?type=read // JSON status no need to include cal schedule
<host>?type=json // JSON full array style, need full parser to pass.
* // Cfg options
* ?type=option&option=24hdelay&state=off // turn off 24h delay
* ?type=option&option=calendar&state=off // turn off calendar
<host>?type=option&option=24hdelay&state=off // turn off 24h delay
<host>?type=option&option=calendar&state=off // turn off calendar
<host>?type=option&option=24hdelay&state=reset // reset time on 24h delay
* // Calendar
* ?type=calcfg&day=3&zone=&time=07:00 // Use default water zone times
* ?type=calcfg&day=2&zone=1&time=7 // Change water zone time
* ?type=calcfg&day=3&zone=&time= // Delete day schedule
<host>?type=calcfg&day=3&zone=&time=07:00 // Use default water zone times
<host>?type=calcfg&day=2&zone=1&time=7 // Change water zone time
<host>?type=calcfg&day=3&zone=&time= // Delete day schedule
* // Run options
* ?type=option&option=allz&state=on // Run all zones default times
* ?type=zone&zone=2&state=on&runtime=3 // Run zone 2 for 3 mins (ignore 24h delay & calendar settings)
* ?type=zrtcfg&zone=2&time=10 // change zone 2 default runtime to 10
* ?type=cron&zone=1&runtime=12' // Run zone 1 for 12 mins (calendar & 24hdelay settings overide this request)
The JSON that's returned is completley flat, this is so it can be passed with really small lightweight passers, even grep and awk. I will eventually add a more complex JSON output that will make it better for people using fill JSON object passers.
<host>?type=option&option=allz&state=on // Run all zones default times
<host>?type=zone&zone=2&state=on&runtime=3 // Run zone 2 for 3 mins (ignore 24h delay & calendar settings)
<host>?type=zrtcfg&zone=2&time=10 // change zone 2 default runtime to 10
<host>?type=cron&zone=1&runtime=12' // Run zone 1 for 12 mins (calendar & 24hdelay settings overide this request)
```
The JSON that's returned is completley flat, this is so it can be passed with really small lightweight passers, even grep and awk. If you want a full JSON with arrays that's easier to use with full json parsers you can use the below
```
<host>?type=json
```
## Apple HomeKit

View File

@ -7,8 +7,10 @@
#ifdef USE_WIRINGPI
#include <wiringPi.h>
#define PIN_CFG_NAME "WPI_PIN"
#else
#include "sd_GPIO.h"
#define PIN_CFG_NAME "GPIO_PIN"
#endif
#include "minIni.h"
@ -16,7 +18,6 @@
#include "config.h"
#define sizearray(a) (sizeof(a) / sizeof((a)[0]))
#define MAXCFGLINE 256
@ -249,7 +250,7 @@ void readCfg(char *inifile)
for (i=1; i <= 24; i++) // 24 = Just some arbutary number (max GPIO without expansion board)
{
sprintf(str, "ZONE:%d", i);
pin = ini_getl(str, "GPIO_PIN", -1, inifile);
pin = ini_getl(str, PIN_CFG_NAME, -1, inifile);
if (pin == -1)
break;
else
@ -267,11 +268,7 @@ void readCfg(char *inifile)
for (i=0; i <= _sdconfig_.zones; i++)
{
sprintf(str, "ZONE:%d", i);
#ifdef USE_WIRINGPI
int pin = ini_getl(str, "WPI_PIN", -1, inifile);
#else
int pin = ini_getl(str, "GPIO_PIN", -1, inifile);
#endif
pin = ini_getl(str, PIN_CFG_NAME, -1, inifile);
if (pin != -1) {
logMessage (LOG_DEBUG, "ZONE = %d\n", i);
if (i==0) {
@ -307,8 +304,8 @@ void readCfg(char *inifile)
}
}
_sdconfig_.pinscfgs = idx;
logMessage (LOG_DEBUG,"Config: total GPIO pins = %d\n",_sdconfig_.pinscfgs);
//_sdconfig_.pinscfgs = idx;
//logMessage (LOG_DEBUG,"Config: total GPIO pins = %d\n",_sdconfig_.pinscfgs);
_sdconfig_.cron[0].zruntimes = malloc(_sdconfig_.zones * sizeof(int));
_sdconfig_.cron[1].zruntimes = malloc(_sdconfig_.zones * sizeof(int));
@ -323,4 +320,43 @@ void readCfg(char *inifile)
logMessage (LOG_ERR," no config zones set\n");
exit (EXIT_FAILURE);
}
/*
idx=0;
pin=-1;
// Caculate how many gpio cfg we have
for (i=1; i <= 24; i++) // 24 = Just some arbutary number (max GPIO without expansion board)
{
sprintf(str, "GPIO:%d", i);
pin = ini_getl(str, PIN_CFG_NAME, -1, inifile);
if (pin == -1)
break;
else
_sdconfig_.pincfgs = i;
}
logMessage (LOG_DEBUG, "Found %d GPIO PINS\n", _sdconfig_.pincfgs);
if ( _sdconfig_.pincfgs != 0) {
// n= _sdconfig_.zones+1;
_sdconfig_.gpiocfg = malloc((_sdconfig_.pincfgs + 1) * sizeof(struct GPIOcfg));
for (i=0; i <= _sdconfig_.pincfgs; i++)
{
sprintf(str, "GPIO:%d", i);
int pin = ini_getl(str, PIN_CFG_NAME, -1, inifile);
if (pin != -1) {
logMessage (LOG_DEBUG, "ZONE = %d\n", i);
_sdconfig_.pincfgs[i].input_output = OUTPUT; // Zone is always output
_sdconfig_.pincfgs[i].receive_mode = BOTH; // Zone always needs trigger on both (high or low)
ini_gets(str, "NAME", NULL, _sdconfig_.pincfgs[idx].name, sizearray(_sdconfig_.pincfgs[idx].name), inifile);
_sdconfig_.pincfgs[i].pin = pin;
_sdconfig_.pincfgs[i].on_state = ini_getl(str, "GPIO_ON_STATE", NO, inifile);
_sdconfig_.pincfgs[i].startup_state = !_sdconfig_.pincfgs[i].on_state;
_sdconfig_.pincfgs[i].shutdown_state = !_sdconfig_.pincfgs[i].on_state;
_sdconfig_.pincfgs[i].set_pull_updown = ini_getl(str, "GPIO_PULL_UPDN", -1, inifile);
}
}
*/
}

View File

@ -17,13 +17,19 @@
#define LABEL_SIZE 40
#define NON_ZONE_DZIDS 3
#define COMMAND_SIZE 512
struct CALENDARday {
int hour;
int minute;
int *zruntimes;
};
/*
struct GPIOextra {
char command_high[COMMAND_SIZE];
char command_low[COMMAND_SIZE];
};
*/
struct GPIOcfg {
int pin;
int input_output;
@ -37,10 +43,11 @@ struct GPIOcfg {
int startup_state;
int shutdown_state;
int dz_idx;
int ignore_requests;
//int ignore_requests;
int zone;
int default_runtime;
bool master_valve;
//struct GPIOextra *extra;
};
struct DZcache {
@ -64,14 +71,15 @@ struct sprinklerdcfg {
int dzidx_allzones;
bool enableMQTTdz;
bool enableMQTTaq;
int pinscfgs;
int zones;
//int pincfgs;
bool system;
bool delay24h;
long delay24h_time;
bool master_valve;
struct DZcache *dz_cache;
struct GPIOcfg *zonecfg;
//struct GPIOcfg *gpiocfg;
struct CALENDARday cron[7];
//time_t cron_update;
long cron_update;

View File

@ -80,7 +80,7 @@ int build_sprinkler_JSON(char* buffer, int size)
int build_advanced_sprinkler_JSON(char* buffer, int size)
{
int i;
int i, day;
memset(&buffer[0], 0, size);
int length = 0;
@ -102,8 +102,27 @@ int build_advanced_sprinkler_JSON(char* buffer, int size)
_sdconfig_.zonecfg[i].default_runtime
);
}
if (_sdconfig_.currentZone.type != zcNONE)
length += sprintf(buffer+length, "\"active\": {\"zone\": %d, \"name\": \"%s\"},",_sdconfig_.currentZone.zone, _sdconfig_.zonecfg[_sdconfig_.currentZone.zone].name);
length += sprintf(buffer+length-1, "}}");
length -= 1;
length += sprintf( buffer+length , "}, \"calendar\": {" );
for (day=0; day <= 6; day++) {
if (_sdconfig_.cron[day].hour >= 0 && _sdconfig_.cron[day].minute >= 0) {
length += sprintf(buffer+length, "\"day %d\" : { \"start time\" : \"%.2d:%.2d\", ",day,_sdconfig_.cron[day].hour,_sdconfig_.cron[day].minute);
for (i=0; i < _sdconfig_.zones; i ++) {
if (_sdconfig_.cron[day].zruntimes[i] >= 0) {
length += sprintf(buffer+length, "\"Zone %d\" : %d,",i+1,_sdconfig_.cron[day].zruntimes[i]);
//logMessage(LOG_DEBUG, "Zone %d, length %d limit %d\n",i+1,length,size);
}
}
length -= 1;
length += sprintf(buffer+length, "},");
}
}
length -= 1;
length += sprintf(buffer+length, "}}");
buffer[length] = '\0';
return strlen(buffer);

View File

@ -367,7 +367,12 @@ int serve_web_request(struct mg_connection *nc, struct http_message *http_msg, c
length = build_sprinkler_JSON(buffer, size);
} else if (strncasecmp(buf, "24hdelay", 8) == 0 ) {
mg_get_http_var(&http_msg->query_string, "state", buf, buflen);
enable_delay24h(is_value_ON(buf));
int val = is_value_ON(buf);
if (val == true || val == false) {
enable_delay24h(val);
} else if (strncasecmp(buf, "reset", 5) == 0) {
reset_delay24h_time();
}
length = build_sprinkler_JSON(buffer, size);
} else if (strncasecmp(buf, "allz", 8) == 0 ) {
mg_get_http_var(&http_msg->query_string, "state", buf, buflen);

Binary file not shown.

View File

@ -118,3 +118,24 @@ WPI_PIN=22
GPIO_PULL_UPDN=1
GPIO_ON_STATE=0
DOMOTICZ_IDX=207
#PIN
#NAME name
#PIN_MODE Setup as input or output
#PULL_UPDN setup pull up pull down resistor NONE|PUD_OFF|PUD_DOWN|PUD_UP
#TRIGGER_EVENT_ON trigger_event on NONE|INT_EDGE_SETUP|INT_EDGE_FALLING|INT_EDGE_RISING|INT_EDGE_BOTH
#TRIGGER_EVENT_STATE trigger_event_received_state LOW|HIGH|BOTH
#COMMAND triggered_event_runcmd = external command to run
#DOMOTICZ_IDX Domoticz IDX
[GPIO]
[GPIO:1]
NAME=Rain Sensor
GPIO_PIN=4
WPI_PIN=7
PIN_MODE=0
#PULL_UPDN=0
TRIGGER_EVENT_ON=3
COMMAND_HIGH=/usr/bin/curl -s -o /dev/null 'http://localhost?type=option&option=24hdelay&state=on'
COMMAND_LOW=/usr/bin/curl -s -o /dev/null 'http://localhost?type=option&option=24hdelay&state=off'

454
sd_GPIO.c
View File

@ -4,55 +4,136 @@
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
/*
#include <stdint.h>
#include <sys/time.h>
#include <poll.h>
#include <pthread.h>
*/
#include "sd_GPIO.h"
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include "utils.h"
bool pinExport(int pin)
{
#include "sd_GPIO.h"
char buffer[SYSFS_READ_MAX];
ssize_t bytes_written;
int fd;
fd = open("/sys/class/gpio/export", O_WRONLY);
if (-1 == fd) {
//fprintf(stderr, "Failed to open export for writing!\n");
logMessage (LOG_ERR, "Failed to open '/sys/class/gpio/export' for writing!\n");
return false;
}
bytes_written = snprintf(buffer, SYSFS_READ_MAX, "%d", pin);
write(fd, buffer, bytes_written);
close(fd);
return true;
}
bool pinUnexport(int pin)
#ifndef GPIO_SYSFS_MODE
static volatile uint32_t * _gpioReg = MAP_FAILED;
static bool _ever = false;
void gpioDelay (unsigned int howLong) // Microseconds (1000000 = 1 second)
{
char buffer[SYSFS_READ_MAX];
ssize_t bytes_written;
int fd;
fd = open("/sys/class/gpio/unexport", O_WRONLY);
if (-1 == fd) {
//fprintf(stderr, "Failed to open unexport for writing!\n");
logMessage (LOG_ERR, "Failed to open '/sys/class/gpio/unexport' for writing!\n");
return false;
}
bytes_written = snprintf(buffer, SYSFS_READ_MAX, "%d", pin);
write(fd, buffer, bytes_written);
close(fd);
return true;
struct timespec sleeper, dummy ;
sleeper.tv_sec = (time_t)(howLong / 1000) ;
sleeper.tv_nsec = (long)(howLong % 1000) * 1000000 ;
nanosleep (&sleeper, &dummy) ;
}
bool pinMode (int pin, int mode)
bool gpioSetup() {
int fd;
fd = open("/dev/mem", O_RDWR | O_SYNC);
if (fd<0)
{
logMessage (LOG_ERR, "Failed to open '/dev/mem' for GPIO access (are we root?)\n");
return false;
}
_gpioReg = mmap
(
0,
GPIO_LEN,
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_SHARED|MAP_LOCKED,
fd,
GPIO_BASE);
close(fd);
_ever = true;
return true;
}
int pinMode(unsigned gpio, unsigned mode) {
int reg, shift;
reg = gpio / 10;
shift = (gpio % 10) * 3;
_gpioReg[reg] = (_gpioReg[reg] & ~(7 << shift)) | (mode << shift);
return true;
}
int getPinMode(unsigned gpio) {
int reg, shift;
reg = gpio / 10;
shift = (gpio % 10) * 3;
return (*(_gpioReg + reg) >> shift) & 7;
}
int digitalRead(unsigned gpio) {
unsigned bank, bit;
bank = gpio >> 5;
bit = (1 << (gpio & 0x1F));
if ((*(_gpioReg + GPLEV0 + bank) & bit) != 0)
return 1;
else
return 0;
}
int digitalWrite(unsigned gpio, unsigned level) {
unsigned bank, bit;
bank = gpio >> 5;
bit = (1 << (gpio & 0x1F));
if (level == 0)
*(_gpioReg + GPCLR0 + bank) = bit;
else
*(_gpioReg + GPSET0 + bank) = bit;
return 0;
}
int setPullUpDown(unsigned gpio, unsigned pud)
{
unsigned bank, bit;
bank = gpio >> 5;
bit = (1 << (gpio & 0x1F));
/*
if (gpio > PI_MAX_GPIO)
SOFT_ERROR(PI_BAD_GPIO, "bad gpio (%d)", gpio);
*/
if (pud > PUD_UP || pud < PUD_OFF)
return false;
//SOFT_ERROR(PI_BAD_PUD, "gpio %d, bad pud (%d)", gpio, pud);
*(_gpioReg + GPPUD) = pud;
gpioDelay(1);
*(_gpioReg + GPPUDCLK0 + bank) = bit;
gpioDelay(1);
*(_gpioReg + GPPUD) = 0;
*(_gpioReg + GPPUDCLK0 + bank) = 0;
return true;
}
#else
bool gpioSetup() {return true;}
int pinMode (unsigned pin, unsigned mode)
{
//static const char s_directions_str[] = "in\0out\0";
@ -85,7 +166,7 @@ bool pinMode (int pin, int mode)
return true;
}
int digitalRead (int pin)
int digitalRead (unsigned pin)
{
char path[SYSFS_PATH_MAX];
char value_str[SYSFS_READ_MAX];
@ -111,7 +192,7 @@ int digitalRead (int pin)
return(atoi(value_str));
}
bool digitalWrite (int pin, int value)
int digitalWrite (unsigned pin, unsigned value)
{
//static const char s_values_str[] = "01";
@ -137,35 +218,157 @@ bool digitalWrite (int pin, int value)
close(fd);
return true;
}
#endif
/*
int waitForInterrupt (int pin, int mS)
bool isExported(unsigned pin)
{
char path[SYSFS_PATH_MAX];
int fd, x ;
char path[SYSFS_PATH_MAX];
struct stat sb;
snprintf(path, SYSFS_PATH_MAX, "/sys/class/gpio/gpio%d/", pin);
if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode))
return true;
else
return false;
}
bool pinExport(unsigned pin)
{
char buffer[SYSFS_READ_MAX];
ssize_t bytes_written;
int fd;
fd = open("/sys/class/gpio/export", O_WRONLY);
if (-1 == fd) {
//fprintf(stderr, "Failed to open export for writing!\n");
logMessage (LOG_ERR, "Failed to open '/sys/class/gpio/export' for writing!\n");
return false;
}
bytes_written = snprintf(buffer, SYSFS_READ_MAX, "%d", pin);
write(fd, buffer, bytes_written);
close(fd);
return true;
}
bool pinUnexport(unsigned pin)
{
char buffer[SYSFS_READ_MAX];
ssize_t bytes_written;
int fd;
fd = open("/sys/class/gpio/unexport", O_WRONLY);
if (-1 == fd) {
//fprintf(stderr, "Failed to open unexport for writing!\n");
logMessage (LOG_ERR, "Failed to open '/sys/class/gpio/unexport' for writing!\n");
return false;
}
bytes_written = snprintf(buffer, SYSFS_READ_MAX, "%d", pin);
write(fd, buffer, bytes_written);
close(fd);
return true;
}
bool edgeSetup (unsigned pin, unsigned value)
{
//static const char s_values_str[] = "01";
char path[SYSFS_PATH_MAX];
int fd;
snprintf(path, SYSFS_PATH_MAX, "/sys/class/gpio/gpio%d/edge", pin);
fd = open(path, O_WRONLY);
if (-1 == fd) {
//fprintf(stderr, "Failed to open gpio value for writing!\n");
logMessage (LOG_ERR, "Failed to open gpio '%s' for writing!\n",path);
return false;
}
int rtn = 0;
if (value==INT_EDGE_RISING)
rtn = write(fd, "rising", 6);
else if (value==INT_EDGE_FALLING)
rtn = write(fd, "falling", 7);
else if (value==INT_EDGE_BOTH)
rtn = write(fd, "both", 4);
else
rtn = write(fd, "none", 4);
if (rtn <= 0) {
logMessage (LOG_ERR, "Failed to setup edge on '%s'!\n",path);
displayLastSystemError("");
return false;
}
close(fd);
return true;
}
#include <poll.h>
#include <pthread.h>
#include <sys/ioctl.h>
struct threadGPIOinterupt{
void (*function)(void *args);
void *args;
unsigned pin;
};
static pthread_mutex_t pinMutex ;
#define MAX_FDS 64
static unsigned int _sysFds [MAX_FDS] =
{
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
} ;
void pushSysFds(int fd)
{
int i;
for (i=0; i< MAX_FDS; i++) {
if (_sysFds[i] == -1) {
_sysFds[i] = fd;
return;
}
}
}
void gpioShutdown() {
int i;
_ever = false;
for (i=0; i< MAX_FDS; i++) {
if (_sysFds[i] != -1) {
printf("Closing fd\n");
close(_sysFds[i]);
_sysFds[i] = -1;
} else {
break;
}
}
}
int waitForInterrupt (int pin, int mS, int fd)
{
int x;
uint8_t c ;
struct pollfd polls ;
//struct pollfd pfd;
sprintf(path, "/sys/class/gpio/gpio%d/value", pin);
if ((fd = open(path, O_RDONLY)) < 0)
{
logMessage (LOG_ERR, "Failed to open '%s'!\n",path);
return -2;
}
// Setup poll structure
// Setup poll structure
polls.fd = fd ;
polls.events = POLLPRI | POLLERR ;
// Wait for it ...
polls.events = POLLPRI | POLLERR | POLLHUP | POLLNVAL;
// Wait for something ...
x = poll (&polls, 1, mS) ;
// If no error, do a dummy read to clear the interrupt
// A one character read appars to be enough.
// If no error, do a dummy read to clear the interrupt
// A one character read appars to be enough.
if (x > 0)
{
@ -176,62 +379,98 @@ int waitForInterrupt (int pin, int mS)
return x ;
}
static volatile int pinPass = -1 ;
static volatile void(*functionPass);
static volatile char(*argsPass);
static pthread_mutex_t pinMutex ;
static void *interruptHandler (void *arg)
{
int myPin ;
struct threadGPIOinterupt *stuff = (struct threadGPIOinterupt *) arg;
int pin = stuff->pin;
void (*function)(void *args) = stuff->function;
void *args = stuff->args;
stuff->pin = -1;
//(void)piHiPri (55) ; // Only effective if we run as root
char path[SYSFS_PATH_MAX];
int fd, count, i ;
uint8_t c ;
myPin = pinPass ;
pinPass = -1 ;
sprintf(path, "/sys/class/gpio/gpio%d/value", pin);
for (;;)
if (waitForInterrupt (myPin, -1) > 0)
printf("READ SOMETHING\n");
//(*function)(arg);
if ((fd = open(path, O_RDONLY)) < 0)
{
logMessage (LOG_ERR, "Failed to open '%s'!\n",path);
return NULL;
}
pushSysFds(fd);
// Clear any initial pending interrupt
ioctl (fd, FIONREAD, &count) ;
for (i = 0 ; i < count ; ++i)
read (fd, &c, 1);
while (_ever == true) {
if (waitForInterrupt (pin, -1, fd) > 0) {
function(args);
} else {
printf("SOMETHING FAILED, reset\n");
gpioDelay(1);
}
}
printf("interruptHandler ended\n");
close(fd);
return NULL ;
}
bool registerGPIOinterrupt(int pin, int mode, void (*function)(char *), void (*args) )
bool registerGPIOinterrupt(int pin, int mode, void (*function)(void *args), void *args )
{
pthread_t threadId ;
// Clear any initial pending interrupt
struct threadGPIOinterupt stuff;
// Check it's exported
if (! isExported(pin))
pinExport(pin);
pinPass = pin ;
// if the pin is putput, set as input to setup edge then reset to output.
if (getPinMode(pin) == OUTPUT) {
pinMode(pin, INPUT);
edgeSetup(pin, mode);
pinMode(pin, OUTPUT);
} else {
edgeSetup(pin, mode);
}
stuff.function = function;
stuff.args = args;
stuff.pin = pin;
pthread_mutex_lock (&pinMutex) ;
if (pthread_create (&threadId, NULL, interruptHandler, NULL) < 0)
if (pthread_create (&threadId, NULL, interruptHandler, (void *)&stuff) < 0)
return false;
else {
while (pinPass != -1)
delay (1) ;
while (stuff.pin == pin)
gpioDelay(1);
}
pthread_mutex_unlock (&pinMutex) ;
return true ;
}
*/
//#define TEST_HARNESS
#ifdef TEST_HARNESS
/*
#include <stdarg.h>
#include <errno.h>
#include <string.h>
#include <time.h>
void *myCallBack(void * args) {
printf("Ping\n");
//struct threadGPIOinterupt *stuff = (struct threadGPIOinterupt *) args;
//printf("Pin is %d\n",stuff->pin);
}
void logMessage(int level, char *format, ...)
{
@ -261,14 +500,37 @@ void displayLastSystemError (const char *on_what)
#define PIN 4
#define POUT 27
int main(int argc, char *argv[]) {
int repeat = 10;
int repeat = 3;
// if (-1 == GPIOExport(POUT) || -1 == GPIOExport(PIN))
// return(1);
gpioSetup();
/*
pinUnexport(POUT);
pinUnexport(PIN);
pinExport(POUT);
pinExport(PIN);
sleep(1);
*/
//edgeSetup(POUT, INT_EDGE_BOTH);
if (-1 == pinMode(POUT, OUTPUT) || -1 == pinMode(PIN, INPUT))
return (2);
//edgeSetup(PIN, INT_EDGE_RISING);
//edgeSetup(POUT, INT_EDGE_RISING);
if (pinExport(POUT) != true)
printf("Error exporting pin\n");
if (registerGPIOinterrupt(POUT, INT_EDGE_RISING, (void *)&myCallBack, (void *)&repeat ) != true)
printf("Error registering interupt\n");
if (registerGPIOinterrupt(PIN, INT_EDGE_RISING, (void *)&myCallBack, (void *)&repeat ) != true)
printf("Error registering interupt\n");
do {
printf("I'm writing to GPIO %d (input)\n", digitalRead(PIN), PIN);
@ -282,9 +544,15 @@ int main(int argc, char *argv[]) {
usleep(500 * 1000);
} while (repeat--);
gpioShutdown();
sleep(1);
if (-1 == pinUnexport(POUT) || -1 == pinUnexport(PIN))
return (4);
sleep(1);
return (0);
}
*/
#endif

View File

@ -2,6 +2,12 @@
#ifndef _SD_GPIO_H_
#define _SD_GPIO_H_
/* Use sysfs for ALL gpio activity?
comment out to use memory where we can
*/
//#define GPIO_SYSFS_MODE
#include <syslog.h>
#include <stdbool.h>
@ -25,12 +31,47 @@
#define INT_EDGE_RISING 2
#define INT_EDGE_BOTH 3
#ifndef GPIO_SYSFS_MODE
#define GPIO_BASE 0x20200000
#define GPIO_LEN 0xB4
#define GPSET0 7
#define GPSET1 8
#define GPCLR0 10
#define GPCLR1 11
#define GPLEV0 13
#define GPLEV1 14
// Not used yet.
#define GPPUD 37
#define GPPUDCLK0 38
#define GPPUDCLK1 39
#endif
//#ifndef SYSFS_MODE
bool pinExport(unsigned pin);
bool pinUnexport(unsigned pin);
bool isExported(unsigned pin);
int pinMode(unsigned gpio, unsigned mode);
int getPinMode(unsigned gpio);
int digitalRead(unsigned gpio);
int digitalWrite(unsigned gpio, unsigned level);
int setPullUpDown(unsigned gpio, unsigned pud);
bool gpioSetup();
void gpioShutdown();
bool registerGPIOinterrupt(int pin, int mode, void (*function)(void *args), void *args );
/*
#else
bool pinExport(int pin);
bool pinUnexport(int pin);
bool pinMode (int pin, int mode);
int digitalRead (int pin);
bool digitalWrite (int pin, int value);
#endif
*/
#endif /* _SD_GPIO_H_ */

View File

@ -52,6 +52,18 @@ void enable_delay24h(bool state)
}
}
void reset_delay24h_time()
{
if (_sdconfig_.delay24h != true) {
_sdconfig_.eventToUpdateHappened = true;
}
_sdconfig_.delay24h = true;
time(&_sdconfig_.delay24h_time);
_sdconfig_.delay24h_time = _sdconfig_.delay24h_time + DELAY24H_SEC;
logMessage(LOG_NOTICE, "Reset rain Delay\n");
}
void check_cron() {
if (_sdconfig_.cron_update > 0) {
logMessage(LOG_DEBUG, "Checking if CRON needs to be updated\n");

View File

@ -12,6 +12,7 @@ void write_cron();
void read_cron();
void enable_delay24h(bool state);
bool check_delay24h();
void reset_delay24h_time();
void enable_system(bool state);
#endif // SD_CRON_H_

View File

@ -248,17 +248,30 @@ void main_loop ()
}
#else
logMessage(LOG_DEBUG, "Setting up GPIO\n");
gpioSetup();
for (i=(_sdconfig_.master_valve?0:1); i <= _sdconfig_.zones ; i++)
{
logMessage (LOG_DEBUG, "Setting up Zone %d\n", i);
#ifdef GPIO_SYSFS_MODE
// Only need to export and gain control if in sysfs mode.
pinUnexport(_sdconfig_.zonecfg[i].pin);
pinExport(_sdconfig_.zonecfg[i].pin);
#endif
pinMode (_sdconfig_.zonecfg[i].pin, _sdconfig_.zonecfg[i].input_output);
if ( _sdconfig_.zonecfg[i].startup_state != -1)
digitalWrite(_sdconfig_.zonecfg[i].pin, _sdconfig_.zonecfg[i].startup_state);
/*
// We actually don't need to register a interupt handeler for outputs. But we will for inputs, so leave this here for future use.
if (registerGPIOinterrupt (_sdconfig_.zonecfg[i].pin, _sdconfig_.zonecfg[i].receive_mode, (void *)&event_trigger, (void *)&_sdconfig_.zonecfg[i]) != true)
{
displayLastSystemError ("Unable to set interrupt handler for specified pin, exiting");
exit (EXIT_FAILURE);
}
*/
logMessage (LOG_DEBUG, "Set GPIO %d to %s\n", _sdconfig_.zonecfg[i].pin,(_sdconfig_.zonecfg[i].input_output==OUTPUT?"OUTPUT":"INPUT") );
}
@ -326,6 +339,9 @@ void Daemon_Stop (int signum)
digitalWrite(_sdconfig_.zonecfg[i].pin, _sdconfig_.zonecfg[i].shutdown_state);
}
}
#ifndef USE_WIRINGPI
gpioSetup();
#endif
/*
#ifdef PTHREAD
logMessage (LOG_INFO, "Stopping httpd threads!\n");
@ -341,7 +357,6 @@ void intHandler(int signum) {
int i;
//syslog (LOG_INFO, "Stopping");
logMessage (LOG_INFO, "Stopping!\n");
for (i=(_sdconfig_.master_valve?0:1); i <= _sdconfig_.zones ; i++)
{
if ( _sdconfig_.zonecfg[i].shutdown_state == 0 || _sdconfig_.zonecfg[i].shutdown_state == 1 ) {
@ -350,6 +365,10 @@ void intHandler(int signum) {
}
}
#ifndef USE_WIRINGPI
gpioSetup();
#endif
close(server_sock);
write_cache();
/*

View File

@ -123,7 +123,7 @@ bool zc_zone(zcRunType type, int zone, zcState state, int length) {
//}
if (state == zcON) {
for (i=1; i < _sdconfig_.pinscfgs ; i++)
for (i=1; i < _sdconfig_.zones ; i++)
{
if ( _sdconfig_.zonecfg[i].on_state == digitalRead (_sdconfig_.zonecfg[i].pin)) {
if (zone == i) {