mirror of
https://github.com/eddyem/small_tel.git
synced 2026-06-19 10:26:25 +03:00
fixed some bugs, check @ real system
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
CC = gcc
|
||||
CFLAGS = -Wall -Wextra -fPIC -DEBUG
|
||||
CFLAGS = -Wall -Wextra -fPIC
|
||||
#-DEBUG
|
||||
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)
|
||||
|
||||
weather_clt_example: weather_clt_example.o
|
||||
@@ -32,8 +33,10 @@ chkweather.o: chkweather.c libweather.so
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
|
||||
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:
|
||||
cp libweather.so /usr/local/lib/
|
||||
cp weather_data.h /usr/local/include/
|
||||
cp chkweather weather_proxy /usr/local/bin
|
||||
ldconfig
|
||||
|
||||
@@ -27,10 +27,11 @@ int main() {
|
||||
struct tm *T = localtime(&wd.last_update);
|
||||
strftime(strt, 63, "%F %T", T);
|
||||
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.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(time(NULL) - wd.last_update > 30) errcode = 3;
|
||||
}else{
|
||||
fprintf(stderr, "Failed to get weather data\n");
|
||||
}
|
||||
|
||||
@@ -280,13 +280,13 @@ static void run_daemon(){
|
||||
|
||||
while(running){
|
||||
time_t tnow = time(NULL);
|
||||
int req = -1;
|
||||
int req = -1, goterr = 0;
|
||||
if(sock) req = request_weather_data(sock);
|
||||
if(req == -1){
|
||||
int diff = tnow - lastert;
|
||||
DBG("diff = %d", diff);
|
||||
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_run_client(stype, G.node, 4096))){
|
||||
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 goterr = 0;
|
||||
|
||||
while(sl_sock_readline(sock, line, 255) > 0){
|
||||
DBG("Parse '%s'", line);
|
||||
|
||||
@@ -94,12 +94,6 @@ int main(int argc, char **argv){
|
||||
signal(SIGPIPE, getpipe); // socket disconnected
|
||||
signal(SIGUSR1, 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
|
||||
sl_daemonize();
|
||||
while(1){ // guard for dead processes
|
||||
@@ -117,6 +111,12 @@ int main(int argc, char **argv){
|
||||
}
|
||||
}
|
||||
#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
|
||||
signal(SIGUSR1, signals);
|
||||
signal(SIGUSR2, signals);
|
||||
|
||||
@@ -240,16 +240,17 @@ int collected_amount(){
|
||||
|
||||
int get_collected(val_t *val, int N){
|
||||
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;
|
||||
}
|
||||
pthread_mutex_lock(&datamutex);
|
||||
val_t *dptr = (N < NAMOUNT_OF_DATA) ? &collected_data[N] : &additional_data[N-NAMOUNT_OF_DATA];
|
||||
#ifdef EBUG
|
||||
char buf[KEY_LEN+1];
|
||||
get_fieldname(dptr, buf);
|
||||
DBG("Copied data of %d (u=%d, nm=%s, t=%zd)", N, dptr->value.u, buf, dptr->time);
|
||||
#endif
|
||||
//LOGDBG("tm: %zd; cl: %zd", dptr->time, collected_data[N].time);
|
||||
//#ifdef EBUG
|
||||
//char buf[KEY_LEN+1];
|
||||
//get_fieldname(dptr, buf);
|
||||
//LOGDBG("Copied data of %d (u=%d, nm=%s, t=%zd)", N, dptr->value.u, buf, dptr->time);
|
||||
//#endif
|
||||
*val = *dptr;
|
||||
pthread_mutex_unlock(&datamutex);
|
||||
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){
|
||||
if(!collected || !fresh) return;
|
||||
//LOGDBG("fix_new_data(): collt: %zd, fresht: %zd", collected->time, fresh->time);
|
||||
if(collected->time >= fresh->time){
|
||||
if(!force) return;
|
||||
//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");
|
||||
}
|
||||
// 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) collected->sense = fresh->sense; // take new level
|
||||
//DBG("Refresh collected value");
|
||||
//LOGDBGADD("Refresh time");
|
||||
collected->time = fresh->time;
|
||||
if(collected->type == fresh->type){ // good case
|
||||
memcpy(&collected->value, &fresh->value, sizeof(num_t));
|
||||
@@ -337,7 +344,7 @@ static void update_additional(val_t *value){
|
||||
ERR("realloc()");
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -402,9 +409,10 @@ static weather_cond_t const shtdnflag = {.good = 0.1, .bad = 0.5, .terrible = 0.
|
||||
void refresh_sensval(sensordata_t *s){
|
||||
//FNAME();
|
||||
//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;
|
||||
if(!s || !s->get_value) return;
|
||||
if(!s || !sensor_alive(s) || !s->get_value) return;
|
||||
//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 time_t lasttupdate = 0; // last update time of weather level
|
||||
@@ -495,7 +503,7 @@ void refresh_sensval(sensordata_t *s){
|
||||
if(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_fieldnameval(&value, reason); // copy to `reason` reason of last level increasing
|
||||
force = 1;
|
||||
DBG("reason: %s; forceflag=%u, old=%d", reason, collected_data[NFORCEDSHTDN].value.u, oldshtdn);
|
||||
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){
|
||||
//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_lock(&datamutex);
|
||||
@@ -519,6 +530,7 @@ void refresh_sensval(sensordata_t *s){
|
||||
collected_data[NWINDDIR2].time = curtime;
|
||||
}
|
||||
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].time = curtime;
|
||||
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");
|
||||
time_t _2update = lasttupdate + _3tpoll;
|
||||
//LOGDBG("curtime: %ld, _2update: %ld", curtime, lasttupdate);
|
||||
if(Forbidden){
|
||||
collected_data[NCOMMWEATH].value.u = WEATHER_PROHIBITED;
|
||||
collected_data[NCOMMWEATH].time = curtime;
|
||||
|
||||
@@ -64,3 +64,7 @@ if(LIGHTNING)
|
||||
endif()
|
||||
|
||||
install(TARGETS ${LIBS} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
install(CODE [===[
|
||||
message(STATUS "Run ldconfig")
|
||||
execute_process(COMMAND ldconfig)
|
||||
]===])
|
||||
|
||||
@@ -59,8 +59,6 @@ static void *mainthread(void *s){
|
||||
}else break; // no connection?
|
||||
sleep(1);
|
||||
}
|
||||
DBG("Lost connection -> suicide");
|
||||
sensor->kill(sensor);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -69,7 +67,6 @@ int sensor_init(sensordata_t *s){
|
||||
if(!s) return FALSE;
|
||||
if(!get_shm_block(&sdat, ClientSide)){
|
||||
WARNX("Can't get BTA shared memory block or create main thread");
|
||||
s->kill(s);
|
||||
return FALSE;
|
||||
}
|
||||
s->values = MALLOC(val_t, NAMOUNT);
|
||||
@@ -78,7 +75,6 @@ int sensor_init(sensordata_t *s){
|
||||
strncpy(s->name, SENSOR_NAME, NAME_LEN);
|
||||
if(pthread_create(&s->thread, NULL, mainthread, (void*)s)){
|
||||
WARN("Can't create main thread");
|
||||
s->kill(s);
|
||||
return FALSE;
|
||||
}
|
||||
s->fdes = 0;
|
||||
|
||||
@@ -84,7 +84,6 @@ int sensor_init(sensordata_t *s){
|
||||
s->values[5].value.u = 0;
|
||||
//s->values[6].value.f = 4.5;
|
||||
if(pthread_create(&s->thread, NULL, mainthread, (void*)s)){
|
||||
s->kill(s);
|
||||
return FALSE;
|
||||
}
|
||||
s->fdes = 0;
|
||||
|
||||
@@ -115,8 +115,7 @@ static void *mainthread(void *s){
|
||||
}
|
||||
}
|
||||
}
|
||||
DBG("OOOOps!");
|
||||
sensor->kill(sensor);
|
||||
// newer use `kill` here! Master will run it after main thread death
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -132,11 +131,9 @@ int sensor_init(sensordata_t *s){
|
||||
for(int i = 0; i < NS; ++i) s->values[i] = values[i];
|
||||
if(!(s->ringbuffer = sl_RB_new(BUFSIZ))){
|
||||
WARNX("Can't init ringbuffer!");
|
||||
s->kill(s);
|
||||
return FALSE;
|
||||
}
|
||||
if(pthread_create(&s->thread, NULL, mainthread, (void*)s)){
|
||||
s->kill(s);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
@@ -99,11 +99,11 @@ enum{
|
||||
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_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)"},
|
||||
[NPOW] = {.sense = VAL_UNNECESSARY, .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"},
|
||||
[NAMBL] = {.sense = VAL_UNNECESSARY, .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"},
|
||||
[NSINCERN] = {.sense = VAL_RECOMMENDED, .type = VALT_UINT, .meaning = IS_OTHER, .name = "TSINCERN", .comment = "Minutes since rain (20 means a lot of)"},
|
||||
[NPOW] = {.sense = VAL_RECOMMENDED, .type = VALT_UINT, .meaning = IS_OTHER, .name = "RAINPOW", .comment = "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_RECOMMENDED, .type = VALT_UINT, .meaning = IS_OTHER, .name = "RSAMBL", .comment = "Ambient light by rain sensor, 0..255"},
|
||||
[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){
|
||||
@@ -119,7 +119,7 @@ static int getv(char s, uint8_t *v){
|
||||
}
|
||||
|
||||
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};
|
||||
static slowregs slow = {0};
|
||||
if(len != REGMINLEN && len != REGLEN){
|
||||
@@ -172,7 +172,7 @@ static void *mainthread(void *s){
|
||||
if(got > 0){
|
||||
buf[--got] = 0;
|
||||
if(encodepacket(buf, got, &Rregs, &Sregs)){
|
||||
DBG("refresh...");
|
||||
//DBG("refresh...");
|
||||
pthread_mutex_lock(&sensor->valmutex);
|
||||
for(int i = 0; i < NAMOUNT; ++i)
|
||||
sensor->values[i].time = tnow;
|
||||
@@ -189,8 +189,6 @@ static void *mainthread(void *s){
|
||||
}
|
||||
}
|
||||
}
|
||||
DBG("OOOOps!");
|
||||
sensor->kill(sensor);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -207,7 +205,6 @@ int sensor_init(sensordata_t *s){
|
||||
for(int i = 0; i < NAMOUNT; ++i) s->values[i] = values[i];
|
||||
if(!(s->ringbuffer = sl_RB_new(BUFSIZ)) ||
|
||||
pthread_create(&s->thread, NULL, mainthread, (void*)s)){
|
||||
s->kill(s);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
@@ -176,8 +176,6 @@ static void *mainthread(void *s){
|
||||
}
|
||||
usleep(1000);
|
||||
}
|
||||
DBG("suicide");
|
||||
sensor->kill(sensor);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -194,7 +192,6 @@ int sensor_init(sensordata_t *s){
|
||||
for(int i = 0; i < NAMOUNT; ++i) s->values[i] = values[i];
|
||||
if(!(s->ringbuffer = sl_RB_new(BUFSIZ)) ||
|
||||
pthread_create(&s->thread, NULL, mainthread, (void*)s)){
|
||||
s->kill(s);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
@@ -39,9 +39,9 @@ enum{
|
||||
static const val_t values[NAMOUNT] = {
|
||||
[NWIND] = {.sense = VAL_RECOMMENDED, .type = VALT_FLOAT, .meaning = IS_WIND},
|
||||
[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},
|
||||
[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},
|
||||
[NPRECIP] = {.sense = VAL_RECOMMENDED, .type = VALT_UINT, .meaning = IS_PRECIP},
|
||||
[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);
|
||||
}
|
||||
}
|
||||
sensor->kill(sensor);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -178,7 +177,6 @@ int sensor_init(sensordata_t *s){
|
||||
for(int i = 0; i < NAMOUNT; ++i) s->values[i] = values[i];
|
||||
if(!(s->ringbuffer = sl_RB_new(BUFSIZ)) ||
|
||||
pthread_create(&s->thread, NULL, mainthread, (void*)s)){
|
||||
s->kill(s);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
@@ -192,9 +192,9 @@ int sensor_init(sensordata_t *s){
|
||||
|
||||
snprintf(s->name, NAME_LEN, "%s", SENSOR_NAME);
|
||||
s->fdes = 0;
|
||||
s->Nvalues = NAMOUNT;
|
||||
s->values = MALLOC(val_t, NAMOUNT);
|
||||
for(int i = 0; i < NAMOUNT; ++i) s->values[i] = values[i];
|
||||
s->Nvalues = NAMOUNT;
|
||||
|
||||
DBG("init OIDs");
|
||||
for(int i = 0; i < OID_AMOUNT; ++i){
|
||||
@@ -209,7 +209,6 @@ int sensor_init(sensordata_t *s){
|
||||
DBG("Start main thread");
|
||||
if(!(s->ringbuffer = sl_RB_new(BUFSIZ)) ||
|
||||
pthread_create(&s->thread, NULL, mainthread, (void*)s)){
|
||||
s->kill(s);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
@@ -43,9 +43,9 @@ static const val_t values[NAMOUNT] = {
|
||||
[NHUMIDITY] = {.sense = VAL_OBLIGATORY, .type = VALT_FLOAT, .meaning = IS_HUMIDITY},
|
||||
[NAMB_TEMP] = {.sense = VAL_OBLIGATORY, .type = VALT_FLOAT, .meaning = IS_AMB_TEMP},
|
||||
[NPRESSURE] = {.sense = VAL_OBLIGATORY, .type = VALT_FLOAT, .meaning = IS_PRESSURE},
|
||||
[NPRECIP] = {.sense = VAL_OBLIGATORY, .type = VALT_UINT, .meaning = IS_PRECIP},
|
||||
[NPRECIPLVL]= {.sense = VAL_RECOMMENDED,.type = VALT_FLOAT, .meaning = IS_PRECIP_LEVEL},
|
||||
[NPRECIPINT]= {.sense = VAL_RECOMMENDED,.type = VALT_FLOAT, .meaning = IS_OTHER, .name = "PRECRATE", .comment = "Precipitation rate, mm/h"},
|
||||
[NPRECIP] = {.sense = VAL_UNNECESSARY, .type = VALT_UINT, .meaning = IS_PRECIP}, // this sensor lies
|
||||
[NPRECIPLVL]= {.sense = VAL_UNNECESSARY,.type = VALT_FLOAT, .meaning = IS_PRECIP_LEVEL},
|
||||
[NPRECIPINT]= {.sense = VAL_UNNECESSARY,.type = VALT_FLOAT, .meaning = IS_OTHER, .name = "PRECRATE", .comment = "Precipitation rate, mm/h"},
|
||||
};
|
||||
|
||||
typedef struct{
|
||||
@@ -106,7 +106,7 @@ static int parseans(char *str){
|
||||
}else{
|
||||
*el->weatherpar = strtod(token, &endptr);
|
||||
if(endptr == token){
|
||||
DBG("Wrong double value %s", token);
|
||||
// DBG("Wrong double value %s", token);
|
||||
}else ++ncollected;
|
||||
}
|
||||
break;
|
||||
@@ -115,7 +115,7 @@ static int parseans(char *str){
|
||||
}
|
||||
token = strtok(NULL, ",");
|
||||
}
|
||||
DBG("Got %d values", ncollected);
|
||||
// DBG("Got %d values", ncollected);
|
||||
return ncollected;
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ static void *mainthread(void *s){
|
||||
WARN("Can't ask new data");
|
||||
break;
|
||||
}
|
||||
DBG("poll @%zd, pollt=%zd", tnow, sensor->tpoll);
|
||||
// DBG("poll @%zd, pollt=%zd", tnow, sensor->tpoll);
|
||||
tpoll = tnow;
|
||||
}
|
||||
int canread = sl_canread(sensor->fdes);
|
||||
@@ -190,7 +190,7 @@ static void *mainthread(void *s){
|
||||
if(sensor->freshdatahandler) sensor->freshdatahandler(sensor);
|
||||
}
|
||||
}
|
||||
sensor->kill(sensor);
|
||||
// newer use `kill` here! Master will run it after main thread death
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -201,12 +201,11 @@ int sensor_init(sensordata_t *s){
|
||||
if(fd < 0) return FALSE;
|
||||
snprintf(s->name, NAME_LEN, "%s", SENSOR_NAME);
|
||||
s->fdes = fd;
|
||||
s->Nvalues = NAMOUNT;
|
||||
s->values = MALLOC(val_t, NAMOUNT);
|
||||
for(int i = 0; i < NAMOUNT; ++i) s->values[i] = values[i];
|
||||
s->Nvalues = NAMOUNT;
|
||||
if(!(s->ringbuffer = sl_RB_new(BUFSIZ)) ||
|
||||
pthread_create(&s->thread, NULL, mainthread, (void*)s)){
|
||||
s->kill(s);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
@@ -56,7 +56,9 @@ time_t get_pollT(){ return poll_interval;}
|
||||
*/
|
||||
sensordata_t *get_plugin(int N){
|
||||
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
|
||||
@@ -85,7 +87,17 @@ void *open_plugin(const char *name){
|
||||
*/
|
||||
static void dumpsensors(struct sensordata_t* station){
|
||||
//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);
|
||||
#if 0
|
||||
DBG("New values...");
|
||||
@@ -124,12 +136,12 @@ int openplugins(char **paths, int N){
|
||||
char buf[PATH_MAX+1];
|
||||
if(!paths || !*paths || N < 1) return 0;
|
||||
if(allplugins || nplugins){
|
||||
WARNXL("Plugins already opened"); return 0;
|
||||
LOGWARN("Plugins already opened"); return 0;
|
||||
}
|
||||
allplugins = MALLOC(sensordata_t*, N);
|
||||
green("Try to open plugins:\n");
|
||||
LOGMSG("Try to open plugins:");
|
||||
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]);
|
||||
char *colon = strchr(buf, ':');
|
||||
if(colon) *colon++ = 0;
|
||||
@@ -145,10 +157,12 @@ int openplugins(char **paths, int N){
|
||||
S->tpoll = poll_interval;
|
||||
allplugins[nplugins++] = S;
|
||||
int inited = sensinit(S); // here nplugins is index in array
|
||||
if(!inited) WARNXL("Can't init plugin %s", paths[i]);
|
||||
else{
|
||||
if(!inited){
|
||||
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");
|
||||
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());
|
||||
@@ -165,6 +179,7 @@ void closeplugins(){
|
||||
for(int i = 0; i < nplugins; ++i){
|
||||
if(allplugins[i]->kill) allplugins[i]->kill(allplugins[i]);
|
||||
FREE(allplugins[i]);
|
||||
LOGWARN("Plugin %d killed", i);
|
||||
}
|
||||
FREE(allplugins);
|
||||
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
|
||||
}
|
||||
|
||||
// put to `buf` string with sensor's name
|
||||
void get_fieldname(const val_t *v, char buf[KEY_LEN+1]){
|
||||
if(!v || !buf) return;
|
||||
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
|
||||
}
|
||||
|
||||
// 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
|
||||
* @param v - value to get
|
||||
|
||||
@@ -41,6 +41,7 @@ time_t get_pollT();
|
||||
|
||||
double val2d(const val_t *v);
|
||||
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_unmute(sensordata_t *s);
|
||||
|
||||
@@ -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)
|
||||
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
|
||||
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;
|
||||
char buf[SSZ_];
|
||||
|
||||
int N = get_nplugins();
|
||||
if(N < 1) return RESULT_FAIL;
|
||||
sensordata_t *d = NULL;
|
||||
for(int i = 0; i < N; ++i){
|
||||
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);
|
||||
else snprintf(buf, SSZ_, "PLUGIN[%d]=%s\nNVALUES[%d]=%d\n", i, d->name, i, d->Nvalues);
|
||||
sl_sock_sendstrmessage(client, buf);
|
||||
send_plugin_name(i, d, client);
|
||||
}
|
||||
return RESULT_SILENCE;
|
||||
}
|
||||
@@ -65,6 +71,7 @@ sensordata_t *get_plugin_w_message(sl_sock_t *client, int N){
|
||||
sl_sock_sendstrmessage(client, buf);
|
||||
return NULL;
|
||||
}
|
||||
send_plugin_name(N, s, client);
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -403,16 +410,19 @@ int start_servers(const char *netnode, const char *sockpath){
|
||||
if(!s) continue;
|
||||
if(sensor_alive(s)) continue;
|
||||
// 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
|
||||
if(s->init){
|
||||
if(s->init(s)) LOGMSG("Sensor %s reinited @ %s", s->name, s->path);
|
||||
else DBG("Can't reinit");
|
||||
if(s->init(s)){
|
||||
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);
|
||||
tstart = tcur;
|
||||
}
|
||||
LOGERR("start_servers(): never reacheable point reached");
|
||||
return TRUE; // should be never reached
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,8 @@ sensordata_t *sensor_new(int N, const char *descr){
|
||||
s->get_value = common_getval;
|
||||
s->kill = common_kill;
|
||||
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);
|
||||
return s;
|
||||
}
|
||||
@@ -51,8 +52,15 @@ sensordata_t *sensor_new(int N, const char *descr){
|
||||
* @return FALSE if thread is dead
|
||||
*/
|
||||
int sensor_alive(sensordata_t *s){
|
||||
if(!s || s->fdes < 0) return FALSE;
|
||||
if(pthread_kill(s->thread, 0)) return FALSE;
|
||||
if(!s || s->fdes < 0){
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -94,6 +102,7 @@ void common_kill(sensordata_t *s){
|
||||
DBG("Delete RB");
|
||||
if(s->ringbuffer) sl_RB_delete(&s->ringbuffer);
|
||||
FREE(s->values);
|
||||
s->Nvalues = 0;
|
||||
if(s->privdatafree) s->privdatafree(s->privdata);
|
||||
else FREE(s->privdata);
|
||||
DBG("Sensor '%s' killed", s->name);
|
||||
|
||||
Reference in New Issue
Block a user