fixed some bugs, check @ real system

This commit is contained in:
2026-05-14 16:23:43 +03:00
parent a31d809c2e
commit bb2af2965a
18 changed files with 135 additions and 81 deletions

View File

@@ -1,10 +1,11 @@
CC = gcc CC = gcc
CFLAGS = -Wall -Wextra -fPIC -DEBUG CFLAGS = -Wall -Wextra -fPIC
#-DEBUG
LDFLAGS = -lrt -pthread -lusefull_macros LDFLAGS = -lrt -pthread -lusefull_macros
all: weather_daemon libweather.so weather_clt_example chkweather all: weather_proxy libweather.so weather_clt_example chkweather
weather_daemon: weather_daemon.o weather_proxy: weather_daemon.o
$(CC) -o $@ $^ $(LDFLAGS) $(CC) -o $@ $^ $(LDFLAGS)
weather_clt_example: weather_clt_example.o weather_clt_example: weather_clt_example.o
@@ -32,8 +33,10 @@ chkweather.o: chkweather.c libweather.so
$(CC) $(CFLAGS) -c $< $(CC) $(CFLAGS) -c $<
clean: clean:
rm -f *.o weather_daemon libweather.so libweather.a weather_clt_example rm -f *.o weather_proxy chkweather libweather.so libweather.a weather_clt_example
install: install:
cp libweather.so /usr/local/lib/ cp libweather.so /usr/local/lib/
cp weather_data.h /usr/local/include/ cp weather_data.h /usr/local/include/
cp chkweather weather_proxy /usr/local/bin
ldconfig

View File

@@ -27,10 +27,11 @@ int main() {
struct tm *T = localtime(&wd.last_update); struct tm *T = localtime(&wd.last_update);
strftime(strt, 63, "%F %T", T); strftime(strt, 63, "%F %T", T);
printf("Windmax=%.1f\nRain=%d\nClouds=%.1f\nWind=%.1f\nExttemp=%.1f\n" printf("Windmax=%.1f\nRain=%d\nClouds=%.1f\nWind=%.1f\nExttemp=%.1f\n"
"Pres=%.1f\nHumid=%.1f\nMeteo=local\nForceOFF=%d\n", "Pres=%.1f\nHumid=%.1f\nMeteo=local\nForceOFF=%d\nWeather=%d\nWeatherTime=%d [%s]\n",
wd.windmax, wd.rain, wd.clouds, wd.wind, wd.exttemp, wd.windmax, wd.rain, wd.clouds, wd.wind, wd.exttemp,
wd.pressure, wd.humidity, wd.forceoff); wd.pressure, wd.humidity, wd.forceoff, (int)wd.weather, (int)wd.last_update, strt);
if(!wd.forceoff) errcode = wd.weather; if(!wd.forceoff) errcode = wd.weather;
if(time(NULL) - wd.last_update > 30) errcode = 3;
}else{ }else{
fprintf(stderr, "Failed to get weather data\n"); fprintf(stderr, "Failed to get weather data\n");
} }

View File

@@ -280,13 +280,13 @@ static void run_daemon(){
while(running){ while(running){
time_t tnow = time(NULL); time_t tnow = time(NULL);
int req = -1; int req = -1, goterr = 0;
if(sock) req = request_weather_data(sock); if(sock) req = request_weather_data(sock);
if(req == -1){ if(req == -1){
int diff = tnow - lastert; int diff = tnow - lastert;
DBG("diff = %d", diff); DBG("diff = %d", diff);
if(diff > RECONN_TMOUT){ // try to reconnect if(diff > RECONN_TMOUT){ // try to reconnect
LOGERR("Failed to request weather data, retry"); if(!goterr){ LOGERR("Failed to request weather data, retry"); goterr = 1; }
if(sock) sl_sock_delete(&sock); if(sock) sl_sock_delete(&sock);
if(!(sock = sl_sock_run_client(stype, G.node, 4096))){ if(!(sock = sl_sock_run_client(stype, G.node, 4096))){
new_data.weather = WEATHER_TERRIBLE; // no connection to weather server, don't allow to open new_data.weather = WEATHER_TERRIBLE; // no connection to weather server, don't allow to open
@@ -298,6 +298,7 @@ static void run_daemon(){
} }
} }
}else if(req == 0) lastert = tnow; }else if(req == 0) lastert = tnow;
else goterr = 0;
while(sl_sock_readline(sock, line, 255) > 0){ while(sl_sock_readline(sock, line, 255) > 0){
DBG("Parse '%s'", line); DBG("Parse '%s'", line);

View File

@@ -94,12 +94,6 @@ int main(int argc, char **argv){
signal(SIGPIPE, getpipe); // socket disconnected signal(SIGPIPE, getpipe); // socket disconnected
signal(SIGUSR1, SIG_IGN); signal(SIGUSR1, SIG_IGN);
signal(SIGUSR2, SIG_IGN); signal(SIGUSR2, SIG_IGN);
int nopened = openplugins(GP->plugins, GP->nplugins);
if(nopened < 1){
LOGERR("No plugins found; exit!");
ERRX("Can't find any sensor plugin");
}
if(GP->nplugins && GP->nplugins != nopened) LOGWARN("Work without some plugins");
#ifndef EBUG #ifndef EBUG
sl_daemonize(); sl_daemonize();
while(1){ // guard for dead processes while(1){ // guard for dead processes
@@ -117,6 +111,12 @@ int main(int argc, char **argv){
} }
} }
#endif #endif
int nopened = openplugins(GP->plugins, GP->nplugins);
if(nopened < 1){
LOGERR("No plugins found; exit!");
ERRX("Can't find any sensor plugin");
}
if(GP->nplugins && GP->nplugins != nopened) LOGWARN("Work without some plugins");
// react for USRx only in child // react for USRx only in child
signal(SIGUSR1, signals); signal(SIGUSR1, signals);
signal(SIGUSR2, signals); signal(SIGUSR2, signals);

View File

@@ -240,16 +240,17 @@ int collected_amount(){
int get_collected(val_t *val, int N){ int get_collected(val_t *val, int N){
if(!val || N < 0 || N >= NAMOUNT_OF_DATA + Nadditional){ if(!val || N < 0 || N >= NAMOUNT_OF_DATA + Nadditional){
DBG("Wrong number (%d) requested or no place for data", N); LOGWARN("get_collected(): wrong number (%d) requested or no place for data", N);
return FALSE; return FALSE;
} }
pthread_mutex_lock(&datamutex); pthread_mutex_lock(&datamutex);
val_t *dptr = (N < NAMOUNT_OF_DATA) ? &collected_data[N] : &additional_data[N-NAMOUNT_OF_DATA]; val_t *dptr = (N < NAMOUNT_OF_DATA) ? &collected_data[N] : &additional_data[N-NAMOUNT_OF_DATA];
#ifdef EBUG //LOGDBG("tm: %zd; cl: %zd", dptr->time, collected_data[N].time);
char buf[KEY_LEN+1]; //#ifdef EBUG
get_fieldname(dptr, buf); //char buf[KEY_LEN+1];
DBG("Copied data of %d (u=%d, nm=%s, t=%zd)", N, dptr->value.u, buf, dptr->time); //get_fieldname(dptr, buf);
#endif //LOGDBG("Copied data of %d (u=%d, nm=%s, t=%zd)", N, dptr->value.u, buf, dptr->time);
//#endif
*val = *dptr; *val = *dptr;
pthread_mutex_unlock(&datamutex); pthread_mutex_unlock(&datamutex);
return TRUE; return TRUE;
@@ -263,6 +264,7 @@ int get_collected(val_t *val, int N){
*/ */
static void fix_new_data(val_t *collected, const val_t *fresh, int force){ static void fix_new_data(val_t *collected, const val_t *fresh, int force){
if(!collected || !fresh) return; if(!collected || !fresh) return;
//LOGDBG("fix_new_data(): collt: %zd, fresht: %zd", collected->time, fresh->time);
if(collected->time >= fresh->time){ if(collected->time >= fresh->time){
if(!force) return; if(!force) return;
//DBG("Forced, collected=%g, fresh=%g", val2d(collected), val2d(fresh)); //DBG("Forced, collected=%g, fresh=%g", val2d(collected), val2d(fresh));
@@ -270,10 +272,15 @@ static void fix_new_data(val_t *collected, const val_t *fresh, int force){
//DBG("Not too old"); //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){
LOGDBG("collected val is too old -> mark as unnecessary");
collected->sense = VAL_UNNECESSARY;
}
//LOGDBGADD("sense coll: %d, fresh: %d", collected->sense, fresh->sense);
if(collected->sense < fresh->sense) return; if(collected->sense < fresh->sense) return;
if(collected->sense != fresh->sense) collected->sense = fresh->sense; // take new level if(collected->sense != fresh->sense) collected->sense = fresh->sense; // take new level
//DBG("Refresh collected value"); //DBG("Refresh collected value");
//LOGDBGADD("Refresh time");
collected->time = fresh->time; collected->time = fresh->time;
if(collected->type == fresh->type){ // good case if(collected->type == fresh->type){ // good case
memcpy(&collected->value, &fresh->value, sizeof(num_t)); memcpy(&collected->value, &fresh->value, sizeof(num_t));
@@ -337,7 +344,7 @@ static void update_additional(val_t *value){
ERR("realloc()"); ERR("realloc()");
} }
memcpy(&additional_data[idx], value, sizeof(val_t)); memcpy(&additional_data[idx], value, sizeof(val_t));
DBG("Allocated new field: %s", value->name); LOGDBG("Allocated new field: %s", value->name);
}else fix_new_data(&additional_data[idx], value, 0); }else fix_new_data(&additional_data[idx], value, 0);
} }
@@ -402,9 +409,10 @@ static weather_cond_t const shtdnflag = {.good = 0.1, .bad = 0.5, .terrible = 0.
void refresh_sensval(sensordata_t *s){ void refresh_sensval(sensordata_t *s){
//FNAME(); //FNAME();
//static time_t poll_time = 0; //static time_t poll_time = 0;
static char reason[KEY_LEN+1] = {0}; // reason of weather level increasing //LOGMSG("Refresh sensval for %d", s->PluginNo);
static char reason[VAL_LEN+1] = {0}; // reason of weather level increasing
val_t value; val_t value;
if(!s || !s->get_value) return; if(!s || !sensor_alive(s) || !s->get_value) return;
//if(poll_time == 0) poll_time = get_pollT(); //if(poll_time == 0) poll_time = get_pollT();
static uint32_t curlevel = 0; // this is worse weather leavel, start from best (collect by all sensors through 3*tpoll) static uint32_t curlevel = 0; // this is worse weather leavel, start from best (collect by all sensors through 3*tpoll)
static time_t lasttupdate = 0; // last update time of weather level static time_t lasttupdate = 0; // last update time of weather level
@@ -495,7 +503,7 @@ void refresh_sensval(sensordata_t *s){
if(curcond){ if(curcond){
int oldshtdn = collected_data[NFORCEDSHTDN].value.u; int oldshtdn = collected_data[NFORCEDSHTDN].value.u;
if(1 == chkweatherlevel(&curlevel, curvalue, curcond)){ if(1 == chkweatherlevel(&curlevel, curvalue, curcond)){
get_fieldname(&value, reason); // copy to `reason` reason of last level increasing get_fieldnameval(&value, reason); // copy to `reason` reason of last level increasing
force = 1; force = 1;
DBG("reason: %s; forceflag=%u, old=%d", reason, collected_data[NFORCEDSHTDN].value.u, oldshtdn); DBG("reason: %s; forceflag=%u, old=%d", reason, collected_data[NFORCEDSHTDN].value.u, oldshtdn);
if(collected_data[NFORCEDSHTDN].value.u - oldshtdn == 1){ // got shutdown if(collected_data[NFORCEDSHTDN].value.u - oldshtdn == 1){ // got shutdown
@@ -505,7 +513,10 @@ void refresh_sensval(sensordata_t *s){
} }
if(idx == NFORCEDSHTDN && value.value.u == 0){ if(idx == NFORCEDSHTDN && value.value.u == 0){
//DBG("Don't clear forced flag by other station"); //DBG("Don't clear forced flag by other station");
}else fix_new_data(&collected_data[idx], &value, force); }else{
//LOGDBG("Call fix_new_data for idx=%d (tcoll=%zd)", idx, collected_data[idx].time);
fix_new_data(&collected_data[idx], &value, force);
}
pthread_mutex_unlock(&datamutex); pthread_mutex_unlock(&datamutex);
} }
pthread_mutex_lock(&datamutex); pthread_mutex_lock(&datamutex);
@@ -519,6 +530,7 @@ void refresh_sensval(sensordata_t *s){
collected_data[NWINDDIR2].time = curtime; collected_data[NWINDDIR2].time = curtime;
} }
if(curtime - collected_data[NWIND].time < tpoll + 1){ if(curtime - collected_data[NWIND].time < tpoll + 1){
//LOGDBG("Update max wind");
collected_data[NWINDMAX].value.f = (float) get_current_max(&windspeeds); collected_data[NWINDMAX].value.f = (float) get_current_max(&windspeeds);
collected_data[NWINDMAX].time = curtime; collected_data[NWINDMAX].time = curtime;
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);
@@ -526,6 +538,7 @@ void refresh_sensval(sensordata_t *s){
} }
//DBG("check ahtung"); //DBG("check ahtung");
time_t _2update = lasttupdate + _3tpoll; time_t _2update = lasttupdate + _3tpoll;
//LOGDBG("curtime: %ld, _2update: %ld", curtime, lasttupdate);
if(Forbidden){ if(Forbidden){
collected_data[NCOMMWEATH].value.u = WEATHER_PROHIBITED; collected_data[NCOMMWEATH].value.u = WEATHER_PROHIBITED;
collected_data[NCOMMWEATH].time = curtime; collected_data[NCOMMWEATH].time = curtime;

View File

@@ -64,3 +64,7 @@ if(LIGHTNING)
endif() endif()
install(TARGETS ${LIBS} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) install(TARGETS ${LIBS} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
install(CODE [===[
message(STATUS "Run ldconfig")
execute_process(COMMAND ldconfig)
]===])

View File

@@ -59,8 +59,6 @@ static void *mainthread(void *s){
}else break; // no connection? }else break; // no connection?
sleep(1); sleep(1);
} }
DBG("Lost connection -> suicide");
sensor->kill(sensor);
return NULL; return NULL;
} }
@@ -69,7 +67,6 @@ int sensor_init(sensordata_t *s){
if(!s) return FALSE; if(!s) return FALSE;
if(!get_shm_block(&sdat, ClientSide)){ if(!get_shm_block(&sdat, ClientSide)){
WARNX("Can't get BTA shared memory block or create main thread"); WARNX("Can't get BTA shared memory block or create main thread");
s->kill(s);
return FALSE; return FALSE;
} }
s->values = MALLOC(val_t, NAMOUNT); s->values = MALLOC(val_t, NAMOUNT);
@@ -78,7 +75,6 @@ int sensor_init(sensordata_t *s){
strncpy(s->name, SENSOR_NAME, NAME_LEN); strncpy(s->name, SENSOR_NAME, NAME_LEN);
if(pthread_create(&s->thread, NULL, mainthread, (void*)s)){ if(pthread_create(&s->thread, NULL, mainthread, (void*)s)){
WARN("Can't create main thread"); WARN("Can't create main thread");
s->kill(s);
return FALSE; return FALSE;
} }
s->fdes = 0; s->fdes = 0;

View File

@@ -84,7 +84,6 @@ int sensor_init(sensordata_t *s){
s->values[5].value.u = 0; s->values[5].value.u = 0;
//s->values[6].value.f = 4.5; //s->values[6].value.f = 4.5;
if(pthread_create(&s->thread, NULL, mainthread, (void*)s)){ if(pthread_create(&s->thread, NULL, mainthread, (void*)s)){
s->kill(s);
return FALSE; return FALSE;
} }
s->fdes = 0; s->fdes = 0;

View File

@@ -115,8 +115,7 @@ static void *mainthread(void *s){
} }
} }
} }
DBG("OOOOps!"); // newer use `kill` here! Master will run it after main thread death
sensor->kill(sensor);
return NULL; return NULL;
} }
@@ -132,11 +131,9 @@ int sensor_init(sensordata_t *s){
for(int i = 0; i < NS; ++i) s->values[i] = values[i]; for(int i = 0; i < NS; ++i) s->values[i] = values[i];
if(!(s->ringbuffer = sl_RB_new(BUFSIZ))){ if(!(s->ringbuffer = sl_RB_new(BUFSIZ))){
WARNX("Can't init ringbuffer!"); WARNX("Can't init ringbuffer!");
s->kill(s);
return FALSE; return FALSE;
} }
if(pthread_create(&s->thread, NULL, mainthread, (void*)s)){ if(pthread_create(&s->thread, NULL, mainthread, (void*)s)){
s->kill(s);
return FALSE; return FALSE;
} }
return TRUE; return TRUE;

View File

@@ -99,11 +99,11 @@ enum{
static const val_t values[NAMOUNT] = { // fields `name` and `comment` have no sense until value meaning is `IS_OTHER` static const val_t values[NAMOUNT] = { // fields `name` and `comment` have no sense until value meaning is `IS_OTHER`
[NPRECIP] = {.sense = VAL_OBLIGATORY, .type = VALT_UINT, .meaning = IS_PRECIP}, [NPRECIP] = {.sense = VAL_OBLIGATORY, .type = VALT_UINT, .meaning = IS_PRECIP},
[NPRECIP_LEVEL] = {.sense = VAL_RECOMMENDED, .type = VALT_FLOAT, .meaning = IS_PRECIP_LEVEL}, [NPRECIP_LEVEL] = {.sense = VAL_RECOMMENDED, .type = VALT_FLOAT, .meaning = IS_PRECIP_LEVEL},
[NSINCERN] = {.sense = VAL_UNNECESSARY, .type = VALT_UINT, .meaning = IS_OTHER, .name = "TSINCERN", .comment = "Minutes since rain (20 means a lot of)"}, [NSINCERN] = {.sense = VAL_RECOMMENDED, .type = VALT_UINT, .meaning = IS_OTHER, .name = "TSINCERN", .comment = "Minutes since rain (20 means a lot of)"},
[NPOW] = {.sense = VAL_UNNECESSARY, .type = VALT_UINT, .meaning = IS_OTHER, .name = "RAINPOW", .comment = "Rain strength, 0..255"}, [NPOW] = {.sense = VAL_RECOMMENDED, .type = VALT_UINT, .meaning = IS_OTHER, .name = "RAINPOW", .comment = "Rain strength, 0..255"},
[NAVG] = {.sense = VAL_UNNECESSARY, .type = VALT_UINT, .meaning = IS_OTHER, .name = "RAINAVG", .comment = "Average rain strength, 0..255"}, [NAVG] = {.sense = VAL_RECOMMENDED, .type = VALT_UINT, .meaning = IS_OTHER, .name = "RAINAVG", .comment = "Average rain strength, 0..255"},
[NAMBL] = {.sense = VAL_UNNECESSARY, .type = VALT_UINT, .meaning = IS_OTHER, .name = "RSAMBL", .comment = "Ambient light by rain sensor, 0..255"}, [NAMBL] = {.sense = VAL_RECOMMENDED, .type = VALT_UINT, .meaning = IS_OTHER, .name = "RSAMBL", .comment = "Ambient light by rain sensor, 0..255"},
[NFREEZ] = {.sense = VAL_UNNECESSARY, .type = VALT_UINT, .meaning = IS_OTHER, .name = "RSFREEZ", .comment = "Rain sensor is freezed"}, [NFREEZ] = {.sense = VAL_RECOMMENDED, .type = VALT_UINT, .meaning = IS_OTHER, .name = "RSFREEZ", .comment = "Rain sensor is freezed"},
}; };
static int getv(char s, uint8_t *v){ static int getv(char s, uint8_t *v){
@@ -119,7 +119,7 @@ static int getv(char s, uint8_t *v){
} }
static int encodepacket(const char *buf, int len, rg11 *Rregs, slowregs *Sregs){ static int encodepacket(const char *buf, int len, rg11 *Rregs, slowregs *Sregs){
DBG("got buffer: %s[%d]", buf, len); // DBG("got buffer: %s[%d]", buf, len);
uint8_t databuf[REGLEN/2] = {0}; uint8_t databuf[REGLEN/2] = {0};
static slowregs slow = {0}; static slowregs slow = {0};
if(len != REGMINLEN && len != REGLEN){ if(len != REGMINLEN && len != REGLEN){
@@ -172,7 +172,7 @@ static void *mainthread(void *s){
if(got > 0){ if(got > 0){
buf[--got] = 0; buf[--got] = 0;
if(encodepacket(buf, got, &Rregs, &Sregs)){ if(encodepacket(buf, got, &Rregs, &Sregs)){
DBG("refresh..."); //DBG("refresh...");
pthread_mutex_lock(&sensor->valmutex); pthread_mutex_lock(&sensor->valmutex);
for(int i = 0; i < NAMOUNT; ++i) for(int i = 0; i < NAMOUNT; ++i)
sensor->values[i].time = tnow; sensor->values[i].time = tnow;
@@ -189,8 +189,6 @@ static void *mainthread(void *s){
} }
} }
} }
DBG("OOOOps!");
sensor->kill(sensor);
return NULL; return NULL;
} }
@@ -207,7 +205,6 @@ int sensor_init(sensordata_t *s){
for(int i = 0; i < NAMOUNT; ++i) s->values[i] = values[i]; for(int i = 0; i < NAMOUNT; ++i) s->values[i] = values[i];
if(!(s->ringbuffer = sl_RB_new(BUFSIZ)) || if(!(s->ringbuffer = sl_RB_new(BUFSIZ)) ||
pthread_create(&s->thread, NULL, mainthread, (void*)s)){ pthread_create(&s->thread, NULL, mainthread, (void*)s)){
s->kill(s);
return FALSE; return FALSE;
} }
return TRUE; return TRUE;

View File

@@ -176,8 +176,6 @@ static void *mainthread(void *s){
} }
usleep(1000); usleep(1000);
} }
DBG("suicide");
sensor->kill(sensor);
return NULL; return NULL;
} }
@@ -194,7 +192,6 @@ int sensor_init(sensordata_t *s){
for(int i = 0; i < NAMOUNT; ++i) s->values[i] = values[i]; for(int i = 0; i < NAMOUNT; ++i) s->values[i] = values[i];
if(!(s->ringbuffer = sl_RB_new(BUFSIZ)) || if(!(s->ringbuffer = sl_RB_new(BUFSIZ)) ||
pthread_create(&s->thread, NULL, mainthread, (void*)s)){ pthread_create(&s->thread, NULL, mainthread, (void*)s)){
s->kill(s);
return FALSE; return FALSE;
} }
return TRUE; return TRUE;

View File

@@ -39,9 +39,9 @@ enum{
static const val_t values[NAMOUNT] = { static const val_t values[NAMOUNT] = {
[NWIND] = {.sense = VAL_RECOMMENDED, .type = VALT_FLOAT, .meaning = IS_WIND}, [NWIND] = {.sense = VAL_RECOMMENDED, .type = VALT_FLOAT, .meaning = IS_WIND},
[NWINDDIR] = {.sense = VAL_RECOMMENDED,.type = VALT_FLOAT, .meaning = IS_WINDDIR}, [NWINDDIR] = {.sense = VAL_RECOMMENDED,.type = VALT_FLOAT, .meaning = IS_WINDDIR},
[NHUMIDITY] = {.sense = VAL_BROKEN, .type = VALT_FLOAT, .meaning = IS_HUMIDITY}, [NHUMIDITY] = {.sense = VAL_BROKEN, .type = VALT_FLOAT, .meaning = IS_HUMIDITY}, // broken on our meteostation
[NAMB_TEMP] = {.sense = VAL_RECOMMENDED, .type = VALT_FLOAT, .meaning = IS_AMB_TEMP}, [NAMB_TEMP] = {.sense = VAL_RECOMMENDED, .type = VALT_FLOAT, .meaning = IS_AMB_TEMP},
[NPRESSURE] = {.sense = VAL_BROKEN, .type = VALT_FLOAT, .meaning = IS_PRESSURE}, [NPRESSURE] = {.sense = VAL_BROKEN, .type = VALT_FLOAT, .meaning = IS_PRESSURE}, // broken on our meteostation
[NCLOUDS] = {.sense = VAL_OBLIGATORY, .type = VALT_FLOAT, .meaning = IS_CLOUDS}, [NCLOUDS] = {.sense = VAL_OBLIGATORY, .type = VALT_FLOAT, .meaning = IS_CLOUDS},
[NPRECIP] = {.sense = VAL_RECOMMENDED, .type = VALT_UINT, .meaning = IS_PRECIP}, [NPRECIP] = {.sense = VAL_RECOMMENDED, .type = VALT_UINT, .meaning = IS_PRECIP},
[NPRECIPLVL]= {.sense = VAL_UNNECESSARY,.type = VALT_FLOAT, .meaning = IS_PRECIP_LEVEL}, [NPRECIPLVL]= {.sense = VAL_UNNECESSARY,.type = VALT_FLOAT, .meaning = IS_PRECIP_LEVEL},
@@ -161,7 +161,6 @@ static void *mainthread(void *s){
if(sensor->freshdatahandler) sensor->freshdatahandler(sensor); if(sensor->freshdatahandler) sensor->freshdatahandler(sensor);
} }
} }
sensor->kill(sensor);
return NULL; return NULL;
} }
@@ -178,7 +177,6 @@ int sensor_init(sensordata_t *s){
for(int i = 0; i < NAMOUNT; ++i) s->values[i] = values[i]; for(int i = 0; i < NAMOUNT; ++i) s->values[i] = values[i];
if(!(s->ringbuffer = sl_RB_new(BUFSIZ)) || if(!(s->ringbuffer = sl_RB_new(BUFSIZ)) ||
pthread_create(&s->thread, NULL, mainthread, (void*)s)){ pthread_create(&s->thread, NULL, mainthread, (void*)s)){
s->kill(s);
return FALSE; return FALSE;
} }
return TRUE; return TRUE;

View File

@@ -192,9 +192,9 @@ int sensor_init(sensordata_t *s){
snprintf(s->name, NAME_LEN, "%s", SENSOR_NAME); snprintf(s->name, NAME_LEN, "%s", SENSOR_NAME);
s->fdes = 0; s->fdes = 0;
s->Nvalues = NAMOUNT;
s->values = MALLOC(val_t, NAMOUNT); s->values = MALLOC(val_t, NAMOUNT);
for(int i = 0; i < NAMOUNT; ++i) s->values[i] = values[i]; for(int i = 0; i < NAMOUNT; ++i) s->values[i] = values[i];
s->Nvalues = NAMOUNT;
DBG("init OIDs"); DBG("init OIDs");
for(int i = 0; i < OID_AMOUNT; ++i){ for(int i = 0; i < OID_AMOUNT; ++i){
@@ -209,7 +209,6 @@ int sensor_init(sensordata_t *s){
DBG("Start main thread"); DBG("Start main thread");
if(!(s->ringbuffer = sl_RB_new(BUFSIZ)) || if(!(s->ringbuffer = sl_RB_new(BUFSIZ)) ||
pthread_create(&s->thread, NULL, mainthread, (void*)s)){ pthread_create(&s->thread, NULL, mainthread, (void*)s)){
s->kill(s);
return FALSE; return FALSE;
} }
return TRUE; return TRUE;

View File

@@ -43,9 +43,9 @@ static const val_t values[NAMOUNT] = {
[NHUMIDITY] = {.sense = VAL_OBLIGATORY, .type = VALT_FLOAT, .meaning = IS_HUMIDITY}, [NHUMIDITY] = {.sense = VAL_OBLIGATORY, .type = VALT_FLOAT, .meaning = IS_HUMIDITY},
[NAMB_TEMP] = {.sense = VAL_OBLIGATORY, .type = VALT_FLOAT, .meaning = IS_AMB_TEMP}, [NAMB_TEMP] = {.sense = VAL_OBLIGATORY, .type = VALT_FLOAT, .meaning = IS_AMB_TEMP},
[NPRESSURE] = {.sense = VAL_OBLIGATORY, .type = VALT_FLOAT, .meaning = IS_PRESSURE}, [NPRESSURE] = {.sense = VAL_OBLIGATORY, .type = VALT_FLOAT, .meaning = IS_PRESSURE},
[NPRECIP] = {.sense = VAL_OBLIGATORY, .type = VALT_UINT, .meaning = IS_PRECIP}, [NPRECIP] = {.sense = VAL_UNNECESSARY, .type = VALT_UINT, .meaning = IS_PRECIP}, // this sensor lies
[NPRECIPLVL]= {.sense = VAL_RECOMMENDED,.type = VALT_FLOAT, .meaning = IS_PRECIP_LEVEL}, [NPRECIPLVL]= {.sense = VAL_UNNECESSARY,.type = VALT_FLOAT, .meaning = IS_PRECIP_LEVEL},
[NPRECIPINT]= {.sense = VAL_RECOMMENDED,.type = VALT_FLOAT, .meaning = IS_OTHER, .name = "PRECRATE", .comment = "Precipitation rate, mm/h"}, [NPRECIPINT]= {.sense = VAL_UNNECESSARY,.type = VALT_FLOAT, .meaning = IS_OTHER, .name = "PRECRATE", .comment = "Precipitation rate, mm/h"},
}; };
typedef struct{ typedef struct{
@@ -106,7 +106,7 @@ static int parseans(char *str){
}else{ }else{
*el->weatherpar = strtod(token, &endptr); *el->weatherpar = strtod(token, &endptr);
if(endptr == token){ if(endptr == token){
DBG("Wrong double value %s", token); // DBG("Wrong double value %s", token);
}else ++ncollected; }else ++ncollected;
} }
break; break;
@@ -115,7 +115,7 @@ static int parseans(char *str){
} }
token = strtok(NULL, ","); token = strtok(NULL, ",");
} }
DBG("Got %d values", ncollected); // DBG("Got %d values", ncollected);
return ncollected; return ncollected;
} }
@@ -131,7 +131,7 @@ static void *mainthread(void *s){
WARN("Can't ask new data"); WARN("Can't ask new data");
break; break;
} }
DBG("poll @%zd, pollt=%zd", tnow, sensor->tpoll); // DBG("poll @%zd, pollt=%zd", tnow, sensor->tpoll);
tpoll = tnow; tpoll = tnow;
} }
int canread = sl_canread(sensor->fdes); int canread = sl_canread(sensor->fdes);
@@ -190,7 +190,7 @@ static void *mainthread(void *s){
if(sensor->freshdatahandler) sensor->freshdatahandler(sensor); if(sensor->freshdatahandler) sensor->freshdatahandler(sensor);
} }
} }
sensor->kill(sensor); // newer use `kill` here! Master will run it after main thread death
return NULL; return NULL;
} }
@@ -201,12 +201,11 @@ int sensor_init(sensordata_t *s){
if(fd < 0) return FALSE; if(fd < 0) return FALSE;
snprintf(s->name, NAME_LEN, "%s", SENSOR_NAME); snprintf(s->name, NAME_LEN, "%s", SENSOR_NAME);
s->fdes = fd; s->fdes = fd;
s->Nvalues = NAMOUNT;
s->values = MALLOC(val_t, NAMOUNT); s->values = MALLOC(val_t, NAMOUNT);
for(int i = 0; i < NAMOUNT; ++i) s->values[i] = values[i]; for(int i = 0; i < NAMOUNT; ++i) s->values[i] = values[i];
s->Nvalues = NAMOUNT;
if(!(s->ringbuffer = sl_RB_new(BUFSIZ)) || if(!(s->ringbuffer = sl_RB_new(BUFSIZ)) ||
pthread_create(&s->thread, NULL, mainthread, (void*)s)){ pthread_create(&s->thread, NULL, mainthread, (void*)s)){
s->kill(s);
return FALSE; return FALSE;
} }
return TRUE; return TRUE;

View File

@@ -56,7 +56,9 @@ time_t get_pollT(){ return poll_interval;}
*/ */
sensordata_t *get_plugin(int N){ sensordata_t *get_plugin(int N){
if(N < 0 || N >= nplugins) return NULL; if(N < 0 || N >= nplugins) return NULL;
return allplugins[N]; sensordata_t *s = allplugins[N];
if(!s || !sensor_alive(s)) s = NULL;
return s;
} }
// TODO: fix for usage with several identical meteostations // TODO: fix for usage with several identical meteostations
@@ -85,7 +87,17 @@ void *open_plugin(const char *name){
*/ */
static void dumpsensors(struct sensordata_t* station){ static void dumpsensors(struct sensordata_t* station){
//FNAME(); //FNAME();
if(!sensor_alive(station) || !station->get_value || station->Nvalues < 1 || station->IsMuted) return; if(!station){
LOGERR("(null) in dumpsensors' station");
return;
}
/*
LOGMSG("alive: %d[%d]", sensor_alive(station), station->PluginNo);
LOGMSGADD("getvalue: %s", station->get_value ? "yes" : "no");
LOGMSGADD("nvalues: %d", station->Nvalues);
LOGMSGADD("ismuted: %d", station->IsMuted);
*/
if(station->Nvalues < 1 || station->IsMuted) return;
refresh_sensval(station); refresh_sensval(station);
#if 0 #if 0
DBG("New values..."); DBG("New values...");
@@ -124,12 +136,12 @@ int openplugins(char **paths, int N){
char buf[PATH_MAX+1]; char buf[PATH_MAX+1];
if(!paths || !*paths || N < 1) return 0; if(!paths || !*paths || N < 1) return 0;
if(allplugins || nplugins){ if(allplugins || nplugins){
WARNXL("Plugins already opened"); return 0; LOGWARN("Plugins already opened"); return 0;
} }
allplugins = MALLOC(sensordata_t*, N); allplugins = MALLOC(sensordata_t*, N);
green("Try to open plugins:\n"); LOGMSG("Try to open plugins:");
for(int i = 0; i < N; ++i){ for(int i = 0; i < N; ++i){
printf("\tplugin[%d]=%s\n", i, paths[i]); LOGMSGADD("plugin[%d]=%s\n", i, paths[i]);
snprintf(buf, PATH_MAX, "%s", paths[i]); snprintf(buf, PATH_MAX, "%s", paths[i]);
char *colon = strchr(buf, ':'); char *colon = strchr(buf, ':');
if(colon) *colon++ = 0; if(colon) *colon++ = 0;
@@ -145,10 +157,12 @@ int openplugins(char **paths, int N){
S->tpoll = poll_interval; S->tpoll = poll_interval;
allplugins[nplugins++] = S; allplugins[nplugins++] = S;
int inited = sensinit(S); // here nplugins is index in array int inited = sensinit(S); // here nplugins is index in array
if(!inited) WARNXL("Can't init plugin %s", paths[i]); if(!inited){
else{ WARNXL("Can't init plugin %s", paths[i]);
if(S->kill) S->kill(S);
}else{
if(!S->onrefresh || !S->onrefresh(S, dumpsensors)) WARNXL("Can't init refresh funtion"); if(!S->onrefresh || !S->onrefresh(S, dumpsensors)) WARNXL("Can't init refresh funtion");
LOGMSG("Plugin %s nave %d sensors", paths[i], S->Nvalues); LOGMSGADD("Plugin %s nave %d sensors; file descriptor: %d", paths[i], S->Nvalues, S->fdes);
} }
} }
}else WARNXL("Can't find initing function in plugin %s: %s", paths[i], dlerror()); }else WARNXL("Can't find initing function in plugin %s: %s", paths[i], dlerror());
@@ -165,6 +179,7 @@ void closeplugins(){
for(int i = 0; i < nplugins; ++i){ for(int i = 0; i < nplugins; ++i){
if(allplugins[i]->kill) allplugins[i]->kill(allplugins[i]); if(allplugins[i]->kill) allplugins[i]->kill(allplugins[i]);
FREE(allplugins[i]); FREE(allplugins[i]);
LOGWARN("Plugin %d killed", i);
} }
FREE(allplugins); FREE(allplugins);
nplugins = 0; nplugins = 0;
@@ -197,6 +212,7 @@ int format_senssense(const val_t *v, char *buf, int buflen, int Np){
return (got < buflen) ? got : buflen; // full or truncated return (got < buflen) ? got : buflen; // full or truncated
} }
// put to `buf` string with sensor's name
void get_fieldname(const val_t *v, char buf[KEY_LEN+1]){ void get_fieldname(const val_t *v, char buf[KEY_LEN+1]){
if(!v || !buf) return; if(!v || !buf) return;
int idx = v->meaning; int idx = v->meaning;
@@ -210,6 +226,20 @@ void get_fieldname(const val_t *v, char buf[KEY_LEN+1]){
else buf[0] = 0; // empty else buf[0] = 0; // empty
} }
// put to `buf` string "name=value"
void get_fieldnameval(const val_t *v, char buf[VAL_LEN+1]){
if(!v || !buf) return;
int idx = v->meaning;
const char *name = NULL;
if(idx < IS_OTHER){
name = NM[idx];
}else{
name = v->name;
}
if(name) snprintf(buf, VAL_LEN+1, "%s=%g", name, val2d(v));
else buf[0] = 0; // empty
}
/** /**
* @brief format_sensval - snprintf sensor's value into buffer * @brief format_sensval - snprintf sensor's value into buffer
* @param v - value to get * @param v - value to get

View File

@@ -41,6 +41,7 @@ time_t get_pollT();
double val2d(const val_t *v); 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]);
void get_fieldnameval(const val_t *v, char buf[VAL_LEN+1]);
int station_mute(sensordata_t *s); int station_mute(sensordata_t *s);
int station_unmute(sensordata_t *s); int station_unmute(sensordata_t *s);

View File

@@ -40,18 +40,24 @@ static sl_sock_hresult_e timehandler(sl_sock_t *client, _U_ sl_sock_hitem_t *ite
} }
#define SSZ_ (PATH_MAX + 256) #define SSZ_ (PATH_MAX + 256)
static void send_plugin_name(int N, sensordata_t *d, sl_sock_t *client){
if(!d || !client) return;
char buf[SSZ_];
if(d->path[0]) snprintf(buf, SSZ_, "PLUGIN[%d]=%s @ %s\nNVALUES[%d]=%d\n", N, d->name, d->path, N, d->Nvalues);
else snprintf(buf, SSZ_, "PLUGIN[%d]=%s\nNVALUES[%d]=%d\n", N, d->name, N, d->Nvalues);
sl_sock_sendstrmessage(client, buf);
}
// show all connected libraries // show all connected libraries
static sl_sock_hresult_e listhandler(sl_sock_t *client, _U_ sl_sock_hitem_t *item, _U_ const char *req){ static sl_sock_hresult_e listhandler(sl_sock_t *client, _U_ sl_sock_hitem_t *item, _U_ const char *req){
if(!client) return RESULT_FAIL; if(!client) return RESULT_FAIL;
char buf[SSZ_];
int N = get_nplugins(); int N = get_nplugins();
if(N < 1) return RESULT_FAIL; if(N < 1) return RESULT_FAIL;
sensordata_t *d = NULL; sensordata_t *d = NULL;
for(int i = 0; i < N; ++i){ for(int i = 0; i < N; ++i){
if(!(d = get_plugin(i))) continue; if(!(d = get_plugin(i))) continue;
if(d->path[0]) snprintf(buf, SSZ_, "PLUGIN[%d]=%s @ %s\nNVALUES[%d]=%d\n", i, d->name, d->path, i, d->Nvalues); send_plugin_name(i, d, client);
else snprintf(buf, SSZ_, "PLUGIN[%d]=%s\nNVALUES[%d]=%d\n", i, d->name, i, d->Nvalues);
sl_sock_sendstrmessage(client, buf);
} }
return RESULT_SILENCE; return RESULT_SILENCE;
} }
@@ -65,6 +71,7 @@ sensordata_t *get_plugin_w_message(sl_sock_t *client, int N){
sl_sock_sendstrmessage(client, buf); sl_sock_sendstrmessage(client, buf);
return NULL; return NULL;
} }
send_plugin_name(N, s, client);
return s; return s;
} }
@@ -403,16 +410,19 @@ int start_servers(const char *netnode, const char *sockpath){
if(!s) continue; if(!s) continue;
if(sensor_alive(s)) continue; if(sensor_alive(s)) continue;
// sensor isn't inited - try to do it // sensor isn't inited - try to do it
DBG("sensor with path %s isn't inited, try", s->path); LOGWARN("Sensor %s isn't alive, kill and try to reinit", s->path);
s->kill(s); // clear resources s->kill(s); // clear resources
if(s->init){ if(s->init){
if(s->init(s)) LOGMSG("Sensor %s reinited @ %s", s->name, s->path); if(s->init(s)){
else DBG("Can't reinit"); if(s->path[0]) LOGMSG("Sensor %s reinited @ %s", s->name, s->path);
else LOGMSG("Sensor %s reinited", s->name);
}else LOGWARN("Can't reinit");
} }
} }
while((tcur = time(NULL)) - tstart < WeatherConf.reinit_delay) sleep(1); while((tcur = time(NULL)) - tstart < WeatherConf.reinit_delay) sleep(1);
tstart = tcur; tstart = tcur;
} }
LOGERR("start_servers(): never reacheable point reached");
return TRUE; // should be never reached return TRUE; // should be never reached
} }

View File

@@ -40,7 +40,8 @@ sensordata_t *sensor_new(int N, const char *descr){
s->get_value = common_getval; s->get_value = common_getval;
s->kill = common_kill; s->kill = common_kill;
s->PluginNo = N; // `init` shouldn't change this value s->PluginNo = N; // `init` shouldn't change this value
snprintf(s->path, PATH_MAX, "%s", descr); // `init` shouldn't change this value if(descr && *descr) snprintf(s->path, PATH_MAX, "%s", descr); // `init` shouldn't change this value
else s->path[0] = 0; // no path
pthread_mutex_init(&s->valmutex, NULL); pthread_mutex_init(&s->valmutex, NULL);
return s; return s;
} }
@@ -51,8 +52,15 @@ sensordata_t *sensor_new(int N, const char *descr){
* @return FALSE if thread is dead * @return FALSE if thread is dead
*/ */
int sensor_alive(sensordata_t *s){ int sensor_alive(sensordata_t *s){
if(!s || s->fdes < 0) return FALSE; if(!s || s->fdes < 0){
if(pthread_kill(s->thread, 0)) return FALSE; LOGMSG("No sensor or fdes < 0");
return FALSE;
}
if(pthread_kill(s->thread, 0)){
if(s->path[0]) LOGMSG("Sensor's '%s @ %s' main thread is dead", s->name, s->path);
else LOGMSG("Sensor's '%s' main thread is dead", s->name);
return FALSE;
}
return TRUE; return TRUE;
} }
@@ -94,6 +102,7 @@ void common_kill(sensordata_t *s){
DBG("Delete RB"); DBG("Delete RB");
if(s->ringbuffer) sl_RB_delete(&s->ringbuffer); if(s->ringbuffer) sl_RB_delete(&s->ringbuffer);
FREE(s->values); FREE(s->values);
s->Nvalues = 0;
if(s->privdatafree) s->privdatafree(s->privdata); if(s->privdatafree) s->privdatafree(s->privdata);
else FREE(s->privdata); else FREE(s->privdata);
DBG("Sensor '%s' killed", s->name); DBG("Sensor '%s' killed", s->name);