This commit is contained in:
2026-04-29 17:47:23 +03:00
parent 27cfe60fe8
commit 05e57ef012
10 changed files with 203 additions and 94 deletions

View File

@@ -27,7 +27,7 @@ message("Install dir prefix: ${CMAKE_INSTALL_PREFIX}")
add_definitions(-D_XOPEN_SOURCE=1234 -D_DEFAULT_SOURCE -D_GNU_SOURCE add_definitions(-D_XOPEN_SOURCE=1234 -D_DEFAULT_SOURCE -D_GNU_SOURCE
-DPACKAGE_VERSION=\"${VERSION}\" -DMINOR_VERSION=\"${MINOR_VERSION}\" -DMID_VERSION=\"${MID_VERSION}\" -DPACKAGE_VERSION=\"${VERSION}\" -DMINOR_VERSION=\"${MINOR_VERSION}\" -DMID_VERSION=\"${MID_VERSION}\"
-DMAJOR_VERSION=\"${MAJOR_VESION}\") -DMAJOR_VERSION=\"${MAJOR_VERSION}\")
set(CMAKE_COLOR_MAKEFILE ON) set(CMAKE_COLOR_MAKEFILE ON)

View File

@@ -143,7 +143,9 @@ static void compplugins(glob_pars *cmdline, glob_pars *conf){
} }
// don't sort: we need leave priority as user pointed // don't sort: we need leave priority as user pointed
//qsort(newarray, newsize, sizeof(char*), sortstrings); //qsort(newarray, newsize, sizeof(char*), sortstrings);
#ifdef EBUG
DBG("NOW together:"); p = newarray; while(*p) printf("\t%s\n", *p++); DBG("NOW together:"); p = newarray; while(*p) printf("\t%s\n", *p++);
#endif
for(int i = 0; i < newsize-1; ++i){ for(int i = 0; i < newsize-1; ++i){
if(NULL == newarray[i]) continue; if(NULL == newarray[i]) continue;
for(int j = i+1; j < newsize; ++j){ for(int j = i+1; j < newsize; ++j){
@@ -177,7 +179,9 @@ static void compplugins(glob_pars *cmdline, glob_pars *conf){
i = j; i = j;
} }
#endif #endif
#ifdef EBUG
DBG("Result:"); p = newarray; while(*p) printf("\t%s\n", *p++); DBG("Result:"); p = newarray; while(*p) printf("\t%s\n", *p++);
#endif
cmdline->plugins = newarray; cmdline->plugins = newarray;
cmdline->nplugins = nondoubleidx; cmdline->nplugins = nondoubleidx;
} }

View File

@@ -96,6 +96,7 @@ static int opensocket(char *path, sl_socktype_e type){
memcpy(unaddr.sun_path, str, 106); memcpy(unaddr.sun_path, str, 106);
FREE(str); FREE(str);
ai.ai_family = AF_UNIX; ai.ai_family = AF_UNIX;
// TODO: add `socket` and `connect`
} }
break; break;
case SOCKT_NET: case SOCKT_NET:
@@ -121,6 +122,7 @@ static int opensocket(char *path, sl_socktype_e type){
close(sock); sock = -1; close(sock); sock = -1;
} else break; } else break;
} }
freeaddrinfo(res);
break; break;
default: // never reached default: // never reached
WARNX("Unsupported socket type %d", type); WARNX("Unsupported socket type %d", type);
@@ -141,6 +143,7 @@ int getFD(char *path){
char type = *path; char type = *path;
if(path[1] != ':') return -1; // after protocol letter should be delimeter if(path[1] != ':') return -1; // after protocol letter should be delimeter
path += 2; path += 2;
if(!*path) return -1; // empty path
switch(type){ switch(type){
case 'D': // serial device case 'D': // serial device
return openserial(path); return openserial(path);

View File

@@ -40,12 +40,12 @@ void signals(int signo){
LOGDBG("Child gotta signal %d", signo); LOGDBG("Child gotta signal %d", signo);
if(signo == SIGUSR1){ if(signo == SIGUSR1){
forbid_observations(1); forbid_observations(1);
LOGMSG("Got signal `observations forbidden`"); LOGWARN("Got signal `observations forbidden`, set FORBIDDEN");
signal(signo, signals); signal(signo, signals);
return; return;
}else if(signo == SIGUSR2){ }else if(signo == SIGUSR2){
forbid_observations(0); forbid_observations(0);
LOGMSG("Got signal `observations permitted`"); LOGWARN("Got signal `observations permitted`, clear FORBIDDEN");
signal(signo, signals); signal(signo, signals);
return; return;
} }
@@ -121,7 +121,7 @@ int main(int argc, char **argv){
signal(SIGUSR1, signals); signal(SIGUSR1, signals);
signal(SIGUSR2, signals); signal(SIGUSR2, signals);
if(!start_servers(GP->port, GP->sockname)) ERRX("Can't run server's threads"); if(!start_servers(GP->port, GP->sockname)) ERRX("Can't run server's threads");
while(1); while(1) pause();
//WARNX("TEST ends"); //WARNX("TEST ends");
//signals(0); //signals(0);
return 0; // never reached return 0; // never reached

View File

@@ -77,18 +77,68 @@ static val_t collected_data[NAMOUNT_OF_DATA] = {
[NMIST] = {.sense = VAL_BROKEN, .type = VALT_UINT, .meaning = IS_MIST}, [NMIST] = {.sense = VAL_BROKEN, .type = VALT_UINT, .meaning = IS_MIST},
[NCLOUDS] = {.sense = VAL_BROKEN, .type = VALT_FLOAT, .meaning = IS_CLOUDS}, [NCLOUDS] = {.sense = VAL_BROKEN, .type = VALT_FLOAT, .meaning = IS_CLOUDS},
[NSKYTEMP] = {.sense = VAL_BROKEN, .type = VALT_FLOAT, .meaning = IS_SKYTEMP}, [NSKYTEMP] = {.sense = VAL_BROKEN, .type = VALT_FLOAT, .meaning = IS_SKYTEMP},
[NLIGHTDIST] = {.sense = VAL_FORCEDSHTDN, .type = VALT_FLOAT, .meaning = IS_LIGTDIST},
// these are calculated values // these are calculated values
[NCOMMWEATH] = {.sense = VAL_OBLIGATORY, .type = VALT_UINT, .meaning = IS_OTHER, .name = "WEATHER", .comment = "Weather (0..3: good/bad/terrible/prohibited)"}, [NCOMMWEATH] = {.sense = VAL_OBLIGATORY, .type = VALT_UINT, .meaning = IS_OTHER, .name = "WEATHER", .comment = "Weather (0..3: good/bad/terrible/prohibited)"},
[NLASTAHTUNG] = {.sense = VAL_RECOMMENDED, .type = VALT_UINT, .meaning = IS_OTHER, .name = "EVTTIME", .comment = "UNIX-time of last weather level changing"}, [NLASTAHTUNG] = {.sense = VAL_RECOMMENDED, .type = VALT_UINT, .meaning = IS_OTHER, .name = "EVTTIME", .comment = "UNIX-time of last weather level changing"},
[NAHTUNGRSN] = {.sense = VAL_RECOMMENDED, .type = VALT_STRING, .meaning = IS_OTHER, .name = "EVTRSN", .comment = "Last weather level increasing reason"}, [NAHTUNGRSN] = {.sense = VAL_RECOMMENDED, .type = VALT_STRING, .meaning = IS_OTHER, .name = "EVTRSN", .comment = "Last weather level increasing reason"},
[NLIGHTDIST] = {.sense = VAL_FORCEDSHTDN, .type = VALT_FLOAT, .meaning = IS_LIGTDIST},
// virtual values for weather level / flags changing // virtual values for weather level / flags changing
[NBADWEATH] = {.sense = VAL_BROKEN, .type = VALT_UINT, .meaning = IS_BADWEATH, .name = "BADWEATH", .comment = "Flag changing weather level to 'BAD'"}, [NBADWEATH] = {.sense = VAL_BROKEN, .type = VALT_UINT, .meaning = IS_BADWEATH, .name = "BADWEATH", .comment = "Flag changing weather level to 'BAD'"},
[NTERRWEATH] = {.sense = VAL_BROKEN, .type = VALT_UINT, .meaning = IS_TERRIBLEWEATH, .name = "TERWEATH", .comment = "Flag changing weather level to 'TERRIBLE'"}, [NTERRWEATH] = {.sense = VAL_BROKEN, .type = VALT_UINT, .meaning = IS_TERRIBLEWEATH, .name = "TERWEATH", .comment = "Flag changing weather level to 'TERRIBLE'"},
[NFORCEDSHTDN] = {.sense = VAL_FORCEDSHTDN, .type = VALT_UINT, .meaning = IS_FORCEDSHTDN, .name = "FORCEOFF", .comment = "Station should be powered off NOW"}, [NFORCEDSHTDN] = {.sense = VAL_FORCEDSHTDN, .type = VALT_UINT, .meaning = IS_FORCEDSHTDN, .name = "FORCEOFF", .comment = "All should be powered off NOW"},
// {.sense = VAL_OBLIGATORY, .type = VALT_FLOAT, .meaning = IS_OTHER}, // {.sense = VAL_OBLIGATORY, .type = VALT_FLOAT, .meaning = IS_OTHER},
}; };
/**
* @brief weather_level - set/clear weather level
* @param newlvl - -1 for getter or 0..3 for setter
* @return current weather level
*/
int weather_level(int newlvl){
if(newlvl > -1 && newlvl <= WEATHER_PROHIBITED){
pthread_mutex_lock(&datamutex);
uint32_t curt = time(NULL);
int oldlvl = collected_data[NCOMMWEATH].value.u;
collected_data[NCOMMWEATH].value.u = newlvl;
collected_data[NCOMMWEATH].time = curt;
sprintf(collected_data[NAHTUNGRSN].value.str, "MANUAL");
collected_data[NAHTUNGRSN].time = curt;
collected_data[NLASTAHTUNG].value.u = curt;
collected_data[NLASTAHTUNG].time = curt;
pthread_mutex_unlock(&datamutex);
LOGWARN("Manual changing of weather level from %d to %d", oldlvl, newlvl);
}
pthread_mutex_lock(&datamutex);
int curlevel = collected_data[NCOMMWEATH].value.u;
pthread_mutex_unlock(&datamutex);
return curlevel;
}
/**
* @brief force_off - set/clear `force off` flag
* @param flag - 1 to set, 0 to clear or -1 to get
* @return current value
*/
int force_off(int flag){
if(flag > -1 && flag < 2){
pthread_mutex_lock(&datamutex);
uint32_t curt = time(NULL);
int oldval = collected_data[NFORCEDSHTDN].value.u;
collected_data[NFORCEDSHTDN].value.u = (uint32_t)flag;
if(flag) collected_data[NFORCEDSHTDN].time = curt;
sprintf(collected_data[NAHTUNGRSN].value.str, "MANUAL");
collected_data[NAHTUNGRSN].time = curt;
collected_data[NLASTAHTUNG].value.u = curt;
collected_data[NLASTAHTUNG].time = curt;
pthread_mutex_unlock(&datamutex);
LOGWARN("Manual changing of FORCED SHUTDOWN from %d to %d", oldval, flag);
}
pthread_mutex_lock(&datamutex);
flag = collected_data[NFORCEDSHTDN].value.u;
pthread_mutex_unlock(&datamutex);
return flag;
}
typedef struct{ typedef struct{
double array[MAX_HISTORY]; double array[MAX_HISTORY];
double sum; double sum;
@@ -195,10 +245,20 @@ int get_collected(val_t *val, int N){
return TRUE; return TRUE;
} }
// take only data with `sense value` less than collected have /**
static void fix_new_data(val_t *collected, val_t *fresh){ * @brief fix_new_data - take only data with `sense value` less than collected have and more recent
* @param collected - pointer to collected data
* @param fresh - pointer to fresh data
* @param force - ==1 to force changing even if this data is older
*/
static void fix_new_data(val_t *collected, const val_t *fresh, int force){
if(!collected || !fresh) return; if(!collected || !fresh) return;
if(collected->time > fresh->time) return; if(collected->time >= fresh->time){
if(!force) return;
//DBG("Forced, collected=%g, fresh=%g", val2d(collected), val2d(fresh));
if(collected->time - fresh->time > 60) return;
//DBG("Not too old");
}
// lower `collected` level if data is too old // lower `collected` level if data is too old
if(fresh->time - collected->time > WeatherConf.ahtung_delay) collected->sense = VAL_UNNECESSARY; if(fresh->time - collected->time > WeatherConf.ahtung_delay) collected->sense = VAL_UNNECESSARY;
if(collected->sense < fresh->sense) return; if(collected->sense < fresh->sense) return;
@@ -253,9 +313,15 @@ static void fix_new_data(val_t *collected, val_t *fresh){
} }
} }
// increase weather level if need, also check force shutdown flags /**
// @return 0 if level wasn't changed, or +1 if was increased * @brief chkweatherlevel - increase weather level if need, also check force shutdown flags
static int chkweatherlevel(int *curlevel, double curvalue, weather_cond_t const *curcond){ * @param curlevel - current max weather level
* @param curvalue - current value of sensor data
* @param curcond - conditions for given value
* @return 0 if level wasn't changed, or +1 if was increased
*/
static int chkweatherlevel(uint32_t *curlevel, double curvalue, weather_cond_t const *curcond){
int rtn = 0;
double good = curcond->good, bad = curcond->bad, terrible = curcond->terrible, prohibited = curcond->prohibited; double good = curcond->good, bad = curcond->bad, terrible = curcond->terrible, prohibited = curcond->prohibited;
int haveproh = (prohibited > terrible) ? 1 : 0; // value have `prohibited` field int haveproh = (prohibited > terrible) ? 1 : 0; // value have `prohibited` field
if(curcond->negflag){ // negate if(curcond->negflag){ // negate
@@ -268,30 +334,31 @@ static int chkweatherlevel(int *curlevel, double curvalue, weather_cond_t const
int newlevel = -1; int newlevel = -1;
if(haveproh && curvalue > prohibited){ if(haveproh && curvalue > prohibited){
newlevel = WEATHER_PROHIBITED; newlevel = WEATHER_PROHIBITED;
DBG("---> new level is PROHIBITED, val=%g", curvalue); DBG("---> new level is PROHIBITED, val=%g", (curcond->negflag) ? -curvalue : curvalue);
}else if(curvalue > terrible){ }else if(curvalue > terrible){
newlevel = WEATHER_TERRIBLE; newlevel = WEATHER_TERRIBLE;
DBG("---> new level is TERRIBLE, val=%g", curvalue); DBG("---> new level is TERRIBLE, val=%g", (curcond->negflag) ? -curvalue : curvalue);
}else if(curvalue > bad) newlevel = WEATHER_BAD; }else if(curvalue > bad) newlevel = WEATHER_BAD;
else if(curvalue < good) newlevel = WEATHER_GOOD; else if(curvalue < good) newlevel = WEATHER_GOOD;
if(newlevel == -1) return 0; if(newlevel == -1) return 0;
time_t curt = time(NULL); time_t curt = time(NULL);
if(curcond->shtdnflag && newlevel >= WEATHER_TERRIBLE){ if(curcond->shtdnflag && newlevel >= WEATHER_TERRIBLE){
DBG("Forced shutdown flag is set, curvalue: %g", curvalue); DBG("Forced shutdown flag is set, curvalue: %g", (curcond->negflag) ? -curvalue : curvalue);
// set to one collected data flag and its time // set to one collected data flag and its time
val_t *f = &collected_data[NFORCEDSHTDN]; val_t *f = &collected_data[NFORCEDSHTDN];
f->value.i = 1; f->value.u = 1;
f->time = (int) curt; f->time = (int) curt;
// and set current weather level to prohibited // and set current weather level to prohibited
*curlevel = WEATHER_PROHIBITED; newlevel = WEATHER_PROHIBITED;
rtn = 1;
} }
if(newlevel > *curlevel){ if((uint32_t)newlevel > *curlevel){
// TODO: add logging // TODO: add logging
DBG("local level increased to %d", newlevel); //DBG("local level increased to %d", newlevel);
*curlevel = newlevel; *curlevel = (uint32_t)newlevel;
return 1; rtn = 1;
} }
return 0; return rtn;
} }
// conditions for "bad weather" flag (if it ==1 set BAD WEATH) // conditions for "bad weather" flag (if it ==1 set BAD WEATH)
@@ -310,7 +377,7 @@ void refresh_sensval(sensordata_t *s){
val_t value; val_t value;
if(!s || !s->get_value) return; if(!s || !s->get_value) return;
//if(poll_time == 0) poll_time = get_pollT(); //if(poll_time == 0) poll_time = get_pollT();
int curlevel = 0; // this is worse weather leavel, start from best uint32_t curlevel = 0; // this is worse weather leavel, start from best
time_t curtime = time(NULL); time_t curtime = time(NULL);
double dir = -100., dir2 = -100.; // mean wind directions double dir = -100., dir2 = -100.; // mean wind directions
//DBG("%d meteo values", s->Nvalues); //DBG("%d meteo values", s->Nvalues);
@@ -319,23 +386,22 @@ void refresh_sensval(sensordata_t *s){
if(!s->get_value(s, &value, i) || value.sense > VAL_RECOMMENDED) continue; if(!s->get_value(s, &value, i) || value.sense > VAL_RECOMMENDED) continue;
//DBG("got value"); //DBG("got value");
int idx = -1; int idx = -1;
double curvalue; double curvalue = val2d(&value);
switch(value.type){
case VALT_UINT: curvalue = (double) value.value.u; break;
case VALT_INT: curvalue = (double) value.value.i; break;
case VALT_FLOAT: curvalue = (double) value.value.f; break;
default: curvalue = 0.;
}
const weather_cond_t *curcond = NULL; const weather_cond_t *curcond = NULL;
switch(value.meaning){ switch(value.meaning){
case IS_WIND: case IS_WIND:
idx = NWIND; idx = NWIND;
curcond = &WeatherConf.wind; curcond = &WeatherConf.wind;
// protect collected wind speeds from destruction in case of simultaneous acces from different plugins
pthread_mutex_lock(&datamutex);
add_windspeed(&windspeeds, curvalue, curtime); add_windspeed(&windspeeds, curvalue, curtime);
pthread_mutex_unlock(&datamutex);
break; break;
case IS_WINDDIR: case IS_WINDDIR:
idx = NWINDDIR; idx = NWINDDIR;
pthread_mutex_lock(&datamutex);
wind_dir_add(collected_data[NWIND].value.f, value.value.f, &dir, &dir2); wind_dir_add(collected_data[NWIND].value.f, value.value.f, &dir, &dir2);
pthread_mutex_unlock(&datamutex);
break; break;
case IS_HUMIDITY: case IS_HUMIDITY:
idx = NHUMIDITY; idx = NHUMIDITY;
@@ -389,11 +455,18 @@ void refresh_sensval(sensordata_t *s){
if(idx < 0 || idx >= NAMOUNT_OF_DATA) continue; if(idx < 0 || idx >= NAMOUNT_OF_DATA) continue;
//DBG("IDX=%d", idx); //DBG("IDX=%d", idx);
pthread_mutex_lock(&datamutex); pthread_mutex_lock(&datamutex);
fix_new_data(&collected_data[idx], &value); int force = 0;
if(curcond){ if(curcond){
if(1 == chkweatherlevel(&curlevel, curvalue, curcond)) int oldshtdn = collected_data[NFORCEDSHTDN].value.u;
if(1 == chkweatherlevel(&curlevel, curvalue, curcond)){
get_fieldname(&value, reason); // copy to `reason` reason of last level increasing get_fieldname(&value, reason); // copy to `reason` reason of last level increasing
force = 1;
if(collected_data[NFORCEDSHTDN].value.u - oldshtdn == 1){ // got shutdown
LOGWARN("Forced shutdown flag is set by '%s' of '%s'", reason, s->name);
}
}
} }
fix_new_data(&collected_data[idx], &value, force);
pthread_mutex_unlock(&datamutex); pthread_mutex_unlock(&datamutex);
} }
pthread_mutex_lock(&datamutex); pthread_mutex_lock(&datamutex);
@@ -411,26 +484,34 @@ void refresh_sensval(sensordata_t *s){
collected_data[NWINDMAX1].value.f = (float) get_max_forT(&windspeeds, curtime - T_ONE_HOUR); collected_data[NWINDMAX1].value.f = (float) get_max_forT(&windspeeds, curtime - T_ONE_HOUR);
collected_data[NWINDMAX1].time = curtime; collected_data[NWINDMAX1].time = curtime;
//DBG("check ahtung"); //DBG("check ahtung");
if(Forbidden) collected_data[NCOMMWEATH].value.i = WEATHER_PROHIBITED; if(Forbidden) collected_data[NCOMMWEATH].value.u = WEATHER_PROHIBITED;
else{ else{
if(collected_data[NCOMMWEATH].value.i > curlevel){ // check timeout to make level lower if(collected_data[NCOMMWEATH].value.u > curlevel){ // check timeout to make level lower
// DBG("curtime: %zd, curahtt: %d, diff: %zd, delay: %d", curtime, collected_data[NLASTAHTUNG].value.i, curtime - collected_data[NLASTAHTUNG].value.i, WeatherConf.ahtung_delay); // DBG("curtime: %zd, curahtt: %d, diff: %zd, delay: %d", curtime, collected_data[NLASTAHTUNG].value.u, curtime - collected_data[NLASTAHTUNG].value.u, WeatherConf.ahtung_delay);
if(curtime - collected_data[NLASTAHTUNG].value.i > WeatherConf.ahtung_delay){ if(curtime - collected_data[NLASTAHTUNG].value.u > WeatherConf.ahtung_delay){
DBG("newlevel: %d, current: %d DECREASED", curlevel, collected_data[NCOMMWEATH].value.i); DBG("newlevel: %d, current: %d DECREASED", curlevel, collected_data[NCOMMWEATH].value.u);
collected_data[NCOMMWEATH].value.i = curlevel; if(curlevel < WEATHER_TERRIBLE){ // clear forced shutdown flag
collected_data[NLASTAHTUNG].value.i = curtime; if(collected_data[NFORCEDSHTDN].value.u){
if(1 < snprintf(collected_data[NAHTUNGRSN].value.str, KEY_LEN+1, "%s", reason)) LOGMSGADD("Clear forced shutdown flag");
collected_data[NAHTUNGRSN].time = curtime; DBG("Clear FORCED SHUTDOWN flag");
collected_data[NCOMMWEATH].value.u = WEATHER_TERRIBLE;
}else collected_data[NCOMMWEATH].value.u = curlevel;
collected_data[NFORCEDSHTDN].value.u = 0;
}else --collected_data[NCOMMWEATH].value.u;
collected_data[NCOMMWEATH].time = curtime;
collected_data[NLASTAHTUNG].value.u = curtime;
LOGMSG("Station '%s', decrease weather level to %d", s->name, collected_data[NCOMMWEATH].value.u);
} }
}else{ }else{
if(collected_data[NCOMMWEATH].value.i < curlevel){ // set to worse if(collected_data[NCOMMWEATH].value.u < curlevel){ // set to worse
DBG("newlevel: %d, current: %d INCREASED", curlevel, collected_data[NCOMMWEATH].value.i); DBG("newlevel: %d, current: %d INCREASED", curlevel, collected_data[NCOMMWEATH].value.u);
collected_data[NCOMMWEATH].value.i = curlevel; LOGWARN("Station '%s', sensor '%s', increase weather level to %d", s->name, reason, curlevel);
collected_data[NCOMMWEATH].value.u = curlevel;
if(1 < snprintf(collected_data[NAHTUNGRSN].value.str, KEY_LEN+1, "%s", reason)) if(1 < snprintf(collected_data[NAHTUNGRSN].value.str, KEY_LEN+1, "%s", reason))
collected_data[NAHTUNGRSN].time = curtime; collected_data[NAHTUNGRSN].time = curtime;
} }
if(curlevel){ if(curlevel){
collected_data[NLASTAHTUNG].value.i = curtime; // refresh last ahtung time only for level > good collected_data[NLASTAHTUNG].value.u = curtime; // refresh last ahtung time only for level > good
collected_data[NAHTUNGRSN].time = curtime; collected_data[NAHTUNGRSN].time = curtime;
} }
} }
@@ -441,17 +522,16 @@ void refresh_sensval(sensordata_t *s){
//DBG("Refreshed"); //DBG("Refreshed");
} }
// set/clear `forbid` flag // set/clear `forbid` flag (by signals USR1 and USR2)
void forbid_observations(int f){ void forbid_observations(int f){
if(f) Forbidden = 1; if(f) Forbidden = 1;
else Forbidden = 0; else Forbidden = 0;
int curt = (int) time(NULL); int curt = (int) time(NULL);
pthread_mutex_lock(&datamutex); // don't use mutexes here as this function called from signal handler
collected_data[NLASTAHTUNG].value.i = curt; collected_data[NLASTAHTUNG].value.u = curt;
collected_data[NLASTAHTUNG].time = curt; collected_data[NLASTAHTUNG].time = curt;
sprintf(collected_data[NAHTUNGRSN].value.str, "FORBID"); sprintf(collected_data[NAHTUNGRSN].value.str, "FORBID");
collected_data[NAHTUNGRSN].time = curt; collected_data[NAHTUNGRSN].time = curt;
pthread_mutex_unlock(&datamutex);
DBG("Change FORBID status to %d", f); DBG("Change FORBID status to %d", f);
} }

View File

@@ -59,5 +59,10 @@ int get_collected(val_t *val, int N);
void forbid_observations(int f); void forbid_observations(int f);
int is_forbidden(); int is_forbidden();
void refresh_sensval(sensordata_t *s); void refresh_sensval(sensordata_t *s);
int force_off(int flag);
int weather_level(int new);
//void run_mainweather(); //void run_mainweather();

View File

@@ -55,8 +55,8 @@ static void *mainthread(void *s){
//if(!sensor->values[5].value.u && drand48() > 0.7) sensor->values[5].value.u = 1; //if(!sensor->values[5].value.u && drand48() > 0.7) sensor->values[5].value.u = 1;
time_t cur = time(NULL); time_t cur = time(NULL);
for(int i = 0; i < NS-1; ++i) sensor->values[i].time = cur; for(int i = 0; i < NS-1; ++i) sensor->values[i].time = cur;
f = sensor->values[6].value.f - (drand48() - 0.2) * 100.; f = sensor->values[6].value.f - (drand48() - 0.52);
if(f > 0. && f < 60000){ if(f > 0. && f < 60){
sensor->values[6].value.f = f; sensor->values[6].value.f = f;
sensor->values[6].time = cur; sensor->values[6].time = cur;
} }
@@ -84,7 +84,7 @@ sensordata_t *sensor_new(int N, time_t pollt, int _U_ fd){
s->values[3].value.f = 600.; s->values[3].value.f = 600.;
s->values[4].value.f = 89.; s->values[4].value.f = 89.;
s->values[5].value.u = 0; s->values[5].value.u = 0;
s->values[6].value.f = 54000.; s->values[6].value.f = 4.5;
s->PluginNo = N; s->PluginNo = N;
if(pthread_create(&s->thread, NULL, mainthread, (void*)s)){ if(pthread_create(&s->thread, NULL, mainthread, (void*)s)){
s->kill(s); s->kill(s);

View File

@@ -300,3 +300,14 @@ int change_val_sense(sensordata_t *s, int idx, valsense_t sense){
s->values[idx].sense = sense; s->values[idx].sense = sense;
return TRUE; return TRUE;
} }
double val2d(const val_t *value){
double curvalue;
switch(value->type){
case VALT_UINT: curvalue = (double) value->value.u; break;
case VALT_INT: curvalue = (double) value->value.i; break;
case VALT_FLOAT: curvalue = (double) value->value.f; break;
default: curvalue = 0.;
}
return curvalue;
}

View File

@@ -33,5 +33,6 @@ int format_sensval(const val_t *v, char *buf, int buflen, int Np);
int format_msrmttm(time_t t, char *buf, int buflen, int Np); int format_msrmttm(time_t t, char *buf, int buflen, int Np);
int change_val_sense(sensordata_t *s, int idx, valsense_t sense); int change_val_sense(sensordata_t *s, int idx, valsense_t sense);
int set_pollT(time_t t); int set_pollT(time_t t);
double val2d(const val_t *v);
void get_fieldname(const val_t *v, char buf[KEY_LEN+1]); void get_fieldname(const val_t *v, char buf[KEY_LEN+1]);
time_t get_pollT(); time_t get_pollT();

View File

@@ -126,7 +126,7 @@ static sl_sock_hresult_e gethandler(sl_sock_t *client, _U_ sl_sock_hitem_t *item
// get parameters' level // get parameters' level
static sl_sock_hresult_e getlvlhandler(sl_sock_t *client, _U_ sl_sock_hitem_t *item, const char *req){ static sl_sock_hresult_e getlvlhandler(sl_sock_t *client, _U_ sl_sock_hitem_t *item, const char *req){
if(!client) if(!client) return RESULT_FAIL; if(!client)return RESULT_FAIL;
int N = get_nplugins(); int N = get_nplugins();
if(N < 1) return RESULT_FAIL; if(N < 1) return RESULT_FAIL;
val_t v; val_t v;
@@ -160,7 +160,7 @@ static sl_sock_hresult_e getlvlhandler(sl_sock_t *client, _U_ sl_sock_hitem_t *i
// set parameters' level; format: setlevel=N1:par=level,...,N1:par=level... // set parameters' level; format: setlevel=N1:par=level,...,N1:par=level...
// Nx - "station" number, par - parameter name (like "HUMIDITY"), level - new level (0..3) // Nx - "station" number, par - parameter name (like "HUMIDITY"), level - new level (0..3)
static sl_sock_hresult_e setlvlhandler(sl_sock_t *client, _U_ sl_sock_hitem_t *item, const char *req){ static sl_sock_hresult_e setlvlhandler(sl_sock_t *client, _U_ sl_sock_hitem_t *item, const char *req){
if(!client) if(!client) return RESULT_FAIL; if(!client) return RESULT_FAIL;
int N = get_nplugins(); int N = get_nplugins();
if(N < 1) return RESULT_FAIL; if(N < 1) return RESULT_FAIL;
if(!req) return RESULT_BADVAL; if(!req) return RESULT_BADVAL;
@@ -221,11 +221,15 @@ static sl_sock_hresult_e setlvlhandler(sl_sock_t *client, _U_ sl_sock_hitem_t *i
break; break;
} }
s = end; s = end;
val_t oldval;
int olds = -1;
if(sd->get_value && sd->get_value(sd, &oldval, validx)) olds = oldval.sense;
DBG("%ld\n", val); DBG("%ld\n", val);
if(!change_val_sense(sd, validx, (valsense_t)val)){ if(!change_val_sense(sd, validx, (valsense_t)val)){
result = RESULT_BADVAL; result = RESULT_BADVAL;
break; break;
} }
LOGWARN("Change '%s' of '%s' sense from %d to %ld", sd->name, buf, olds, val);
while(isspace((unsigned char)*s)) s++; while(isspace((unsigned char)*s)) s++;
if(*s == ','){ // omit delimeter if(*s == ','){ // omit delimeter
++s; ++s;
@@ -239,6 +243,44 @@ static sl_sock_hresult_e setlvlhandler(sl_sock_t *client, _U_ sl_sock_hitem_t *i
return result; return result;
} }
static sl_sock_hresult_e forbidhandler(sl_sock_t *client, sl_sock_hitem_t *item, const char *req){
char buf[256];
if(!client) return RESULT_FAIL;
if(req){ // setter
int l;
if(!sl_str2i(&l, req)) return RESULT_BADVAL;
forbid_observations(l);
LOGWARN("Manual set by socket command FORBID=%d", is_forbidden());
}
snprintf(buf, 256, "%s = %d\n", item->key, is_forbidden());
sl_sock_sendstrmessage(client, buf);
return RESULT_SILENCE;
}
static sl_sock_hresult_e forceoffhandler(sl_sock_t *client, sl_sock_hitem_t *item, const char *req){
char buf[256];
if(!client) return RESULT_FAIL;
int flag = -1;
if(req){ // setter
if(!sl_str2i(&flag, req) || flag < 0 || flag > 1) return RESULT_BADVAL;
}
snprintf(buf, 256, "%s = %d\n", item->key, force_off(flag));
sl_sock_sendstrmessage(client, buf);
return RESULT_SILENCE;
}
static sl_sock_hresult_e wlevhandler(sl_sock_t *client, sl_sock_hitem_t *item, const char *req){
char buf[256];
if(!client) return RESULT_FAIL;
int newlevel = -1;
if(req){ // setter
if(!sl_str2i(&newlevel, req) || newlevel < 0 || newlevel > WEATHER_PROHIBITED) return RESULT_BADVAL;
}
snprintf(buf, 256, "%s = %d\n", item->key, weather_level(newlevel));
sl_sock_sendstrmessage(client, buf);
return RESULT_SILENCE;
}
// graceful closing socket: let client know that he's told to fuck off // graceful closing socket: let client know that he's told to fuck off
static void toomuch(int fd){ static void toomuch(int fd){
const char *m = "Try later: too much clients connected\n"; const char *m = "Try later: too much clients connected\n";
@@ -288,27 +330,14 @@ static sl_sock_hitem_t nethandlers[] = { // net - only getters and client-only s
{NULL, NULL, NULL, NULL} {NULL, NULL, NULL, NULL}
}; };
static sl_sock_hitem_t localhandlers[] = { // local - full amount of setters/getters static sl_sock_hitem_t localhandlers[] = { // local - full amount of setters/getters
{forbidhandler, "forbid", "get/set/clear MANUAL FORBID flag", NULL},
{forceoffhandler, "forceoff", "get/set/clear FORCE SHUTDOWN flag", NULL},
{setlvlhandler, "setlevel", "set 'sense level' (0..3) for given plugin parameters, e.g. setlevel=1:WIND=3,HUMIDITY=3 - disable fields for station 1", NULL}, {setlvlhandler, "setlevel", "set 'sense level' (0..3) for given plugin parameters, e.g. setlevel=1:WIND=3,HUMIDITY=3 - disable fields for station 1", NULL},
{wlevhandler, "weathlevel", "set/get current weather level (0..3): goog/bad/terrible/prohibited", NULL},
COMMONHANDLERS COMMONHANDLERS
{NULL, NULL, NULL, NULL} {NULL, NULL, NULL, NULL}
}; };
#if 0
// common parsers for both net and local sockets
static void *cmdparser(void *U){
if(!U) return NULL;
sl_sock_t *s = (sl_sock_t*) U;
while(s && s->connected){
if(!s->rthread){
LOGERR("Server's handlers' thread is dead");
break;
}
}
LOGDBG("cmdparser(): exit");
return NULL;
}
#endif
int start_servers(const char *netnode, const char *sockpath){ int start_servers(const char *netnode, const char *sockpath){
if(!netnode || !sockpath){ if(!netnode || !sockpath){
LOGERR("start_servers(): need arguments"); LOGERR("start_servers(): need arguments");
@@ -334,35 +363,11 @@ int start_servers(const char *netnode, const char *sockpath){
sl_sock_dischandler(localsocket, disconnected); sl_sock_dischandler(localsocket, disconnected);
sl_sock_defmsghandler(netsocket, defhandler); sl_sock_defmsghandler(netsocket, defhandler);
sl_sock_defmsghandler(localsocket, defhandler); sl_sock_defmsghandler(localsocket, defhandler);
#if 0
if(pthread_create(&netthread, NULL, cmdparser, (void*)netsocket)){
LOGERR("Can't run server's net thread");
goto errs;
}
if(pthread_create(&locthread, NULL, cmdparser, (void*)localsocket)){
LOGERR("Can't run server's local thread");
goto errs;
}
#endif
return TRUE; return TRUE;
#if 0
errs:
sl_sock_delete(&localsocket);
sl_sock_delete(&netsocket);
return FALSE;
#endif
} }
void kill_servers(){ void kill_servers(){
//pthread_cancel(locthread);
//pthread_cancel(netthread);
//LOGMSG("Server threads canceled");
//usleep(500);
sl_sock_delete(&localsocket); sl_sock_delete(&localsocket);
sl_sock_delete(&netsocket); sl_sock_delete(&netsocket);
LOGMSG("Server sockets destroyed"); LOGMSG("Server sockets destroyed");
//usleep(500);
//pthread_join(locthread, NULL);
//pthread_join(netthread, NULL);
//LOGMSG("Server threads are dead");
} }