20 Commits

Author SHA1 Message Date
59e3350aaf adjust 1s store period 2020-03-09 12:40:30 +01:00
6c21983917 fix calculation 2020-03-09 12:37:45 +01:00
80103312ce some debug 2020-03-09 12:33:45 +01:00
9213cfac11 some debug 2020-03-09 12:31:47 +01:00
07c80eb21c forgotten inculde 2020-03-09 12:24:09 +01:00
eb83c754bf output 1s 2020-03-09 12:23:16 +01:00
4f81343a89 fix mem stuff 2020-03-09 12:22:13 +01:00
e8102e74a9 1s entries 2020-03-09 12:05:06 +01:00
784346b833 adjust service file 2019-11-14 15:05:17 +01:00
e3ee3a08e8 add restart target 2019-11-14 14:42:11 +01:00
5ef114b634 code beautifying, extended filtering discarded, better adjust epsilon 2019-11-14 14:41:20 +01:00
2dd586d7e4 fix service file 2019-11-13 20:22:05 +00:00
5d1f7dde89 version stuff 2019-11-13 21:14:31 +01:00
8d56c5aff4 enhance makefile 2019-11-12 16:12:33 +01:00
5230139544 store only when settled 2019-11-12 16:02:53 +01:00
08c76f13de save raw freq, add location 2019-11-12 14:43:38 +01:00
6a13da024d add gradient into data 2019-11-08 22:54:56 +01:00
8c0c864905 mark invalid and replaced values in database 2019-11-05 15:07:19 +01:00
61b1498d7b logging 2019-11-05 14:36:38 +01:00
e21e114313 output to stderr 2019-11-04 17:30:45 +01:00
9 changed files with 195 additions and 45 deletions

View File

@ -3,15 +3,49 @@ CC=gcc
CFLAGS=-Wall
LDFLAGS=-lwiringPi -lcurl -lconfig
counter: counter.o LS7366R.o influx.o ringbuffer.o led.o
$(CC) -o $@ $(LDFLAGS) $^
INST_DIR=/opt/sbin
.c.o:
$(CC) $(CFLAGS) -c $<
REFCNT:=$(shell git rev-list --all --count)
VERSION:=$(shell cat VERSION)
.PHONY: all
all: counter
counter: counter.o LS7366R.o influx.o ringbuffer.o led.o logging.o version.o
$(CC) -o $@ $(LDFLAGS) $^
version.o: version.c VERSION
$(CC) -DD_REFCNT=$(REFCNT) -DD_VERSION=\"$(VERSION)\" -c $<
.c.o:
$(CC) $(CFLAGS) -c $<
.PHONY: clean
clean:
-rm -f *.o counter
.PHONY: update
update:
sudo systemctl stop counter
sudo cp counter $(INST_DIR)
sudo systemctl start counter
.PHONY: install
install:
sudo mkdir -p $(INST_DIR)
sudo cp counter counter.service $(INST_DIR)
sudo systemctl enable $(INST_DIR)/counter.service
sudo systemctl start counter
.PHONY: stop
stop:
sudo systemctl stop counter
.PHONY: start
start:
sudo systemctl start counter
.PHONY: restart
restart:
sudo systemctl restart counter

1
src/VERSION Normal file
View File

@ -0,0 +1 @@
0.97

View File

@ -5,13 +5,18 @@
#include <stdio.h>
#include <unistd.h>
#include <libconfig.h>
#include <math.h>
#include "LS7366R.h"
#include "influx.h"
#include "ringbuffer.h"
#include "led.h"
#include "logging.h"
extern char VERSION[];
extern uint32_t REFCNT;
const int CTRL_OUT = 16;
const int INTR_IN = 19;
const int SPI_CHAN = 0;
@ -51,9 +56,9 @@ void init() {
void readConfig() {
config_init(&cfg);
if (! config_read_file(&cfg, "/opt/etc/counter.cfg")) {
fprintf(stderr, "failed to read config file: %s:%d - %s\n",
config_error_file(&cfg), config_error_line(&cfg),
config_error_text(&cfg));
logmsg(LOG_ERR, "failed to read config file: %s:%d - %s\n",
config_error_file(&cfg), config_error_line(&cfg),
config_error_text(&cfg));
config_destroy(&cfg);
exit(-1);
}
@ -64,6 +69,7 @@ void start() {
}
int main (void) {
fprintf(stderr, "VERSION: %s, REFCNT: %u\n", VERSION, REFCNT);
readConfig();
init();
@ -76,31 +82,40 @@ int main (void) {
if (! config_lookup_float(&cfg, EPSILON_KEY, &epsilon)) {
epsilon = DEFAULT_EPSILON;
}
fprintf(stderr, "CONFIG: epsilon=%f\n", epsilon);
double lastF = 0;
bool settled = false;
uint8_t ledTick = 0;
while (1) {
uint32_t diff = ringbufferGet();
double f = 1.0 / (((double) diff) / 1000000.0);
if (settled && (abs(f - lastF) > epsilon)) {
printf("Current f=%f, last f=%f, gradient too large, skipped\n", f, lastF);
while (1) {
uint32_t period = ringbufferGet();
double fRaw = 1.0 / (((double) period) / 1000000.0);
int valid = settled ? 1 : 0;
double gradient = fRaw - lastF;
double fSmoothed = fRaw;
if (settled && (fabs(gradient) > epsilon)) {
logmsg(LOG_INFO, "Current f=%f, last f=%f, gradient %f too large, invalid\n", fRaw, lastF, gradient);
skipped++;
f = lastF;
fSmoothed = lastF;
valid = 0;
} else {
lastF = fRaw;
}
if (settled) {
influxAddFrequency(period, fRaw, fSmoothed, gradient, valid);
}
lastF = f;
// printf("%f\n", f);
influxAddFrequency(f);
ledTick++;
if (ledTick == 50) {
ledTick = 0;
led(E_GREEN, false);
if (! settled) {
printf("Now it is settled\n");
logmsg(LOG_INFO, "Now it is settled\n");
settled = true;
}
}

View File

@ -6,9 +6,7 @@ After=network-online.target
[Service]
Type=simple
GuessMainPID=yes
ExecStart=/opt/bin/counter
ExecStop=kill -SIGINT $mainpid
ExecStart=/opt/sbin/counter
Restart=on-failure
WorkingDirectory=/tmp

View File

@ -1,5 +1,6 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <curl/curl.h>
#include <time.h>
#include <string.h>
@ -7,6 +8,7 @@
#include <libconfig.h>
#include "led.h"
#include "logging.h"
const char INFLUXURL_KEY[] = "influxUrl";
@ -18,6 +20,12 @@ const char INFLUXPASS_KEY[] = "influxPass";
const char *influxPass;
const char INFLUXTAG_KEY[] = "influxTag";
const char *influxTag;
const char DEFAULT_LOCATION[] = "Essen_DE";
const char LOCATION_KEY[] = "location";
const char *location;
const uint8_t ONE_SECOND_DIVIDER = 50;
extern uint32_t skipped;
@ -25,15 +33,34 @@ extern uint32_t skipped;
// #define BUFSIZE 131070
#define BUFSIZE 65535
// #define BUFSIZE 1024
char influxBuffer[BUFSIZE];
char *bufferNextEntry;
// char influxBuffer[BUFSIZE];
// char *bufferNextEntry;
typedef struct influxBuffer {
uint32_t entries;
uint32_t totalEntries;
char *nextEntry;
char buffer[BUFSIZE];
} tInfluxBuffer;
typedef enum {
PERIOD_20MS = 0,
PERIOD_1S,
PERIOD_END
} ePeriod;
tInfluxBuffer *influxBuffers[PERIOD_END];
#define HOSTNAMESIZE 128
char hostname[HOSTNAMESIZE];
static void influxClearBuffer() {
memset(influxBuffer, 0, BUFSIZE);
bufferNextEntry = influxBuffer;
static void influxClearBuffer(tInfluxBuffer *influxBuffer, bool initial) {
memset(influxBuffer->buffer, 0, BUFSIZE);
influxBuffer->nextEntry = influxBuffer->buffer;
influxBuffer->entries = 0;
if (initial) {
influxBuffer->totalEntries = 0;
}
}
@ -41,22 +68,33 @@ void influxInit(config_t *pCfg) {
if (! config_lookup_string(pCfg, INFLUXURL_KEY, &influxUrl)) {
influxUrl = DEFAULT_INFLUXURL;
}
fprintf(stderr, "CONFIG: influxUrl=%s\n", influxUrl);
if (! config_lookup_string(pCfg, INFLUXUSER_KEY, &influxUser)) {
influxUser = NULL;
}
fprintf(stderr, "CONFIG: influxUser=%s\n", (influxUser == NULL ? "<null>" : influxUser));
if (! config_lookup_string(pCfg, INFLUXPASS_KEY, &influxPass)) {
influxPass = NULL;
}
fprintf(stderr, "CONFIG: influxPass=%s\n", (influxPass == NULL ? "<null>" : influxPass));
if (! config_lookup_string(pCfg, LOCATION_KEY, &location)) {
location = DEFAULT_LOCATION;
}
fprintf(stderr, "CONFIG: location=%s\n", location);
if (! config_lookup_string(pCfg, INFLUXTAG_KEY, &influxTag)) {
gethostname(hostname, HOSTNAMESIZE);
influxTag = hostname;
}
influxClearBuffer();
fprintf(stderr, "CONFIG: influxTag=%s\n", influxTag);
influxBuffers[PERIOD_20MS] = (tInfluxBuffer*) malloc(sizeof(tInfluxBuffer));
influxClearBuffer(influxBuffers[PERIOD_20MS], true);
influxBuffers[PERIOD_1S] = (tInfluxBuffer*) malloc(sizeof(tInfluxBuffer));
influxClearBuffer(influxBuffers[PERIOD_1S], true);
}
static void influxSendRequest() {
static void influxSendRequest(tInfluxBuffer *influxBuffer) {
led(E_RED, false);
led(E_BLUE, true);
CURL *curl = curl_easy_init();
@ -67,10 +105,10 @@ static void influxSendRequest() {
curl_easy_setopt(curl, CURLOPT_USERNAME, influxUser);
curl_easy_setopt(curl, CURLOPT_PASSWORD, influxPass);
}
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, influxBuffer);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, influxBuffer->buffer);
CURLcode res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
logmsg(LOG_ERR, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
led(E_RED, true);
}
curl_easy_cleanup(curl);
@ -78,27 +116,64 @@ static void influxSendRequest() {
led(E_BLUE, false);
}
void influxAddFrequency(double f) {
static uint32_t entries = 0;
static uint32_t totalEntries = 0;
void influxAddFrequency(uint32_t period, double fRaw, double fSmoothed, double gradient,
int valid) {
static uint8_t divider = 0;
static uint32_t summedUpTime = 0;
char tmpBuf[256];
struct timespec t;
clock_gettime(CLOCK_REALTIME, &t);
uint64_t tt = (((uint64_t)t.tv_sec) * 1000) + (((uint64_t)t.tv_nsec) / 1000000);
int c = sprintf(tmpBuf, "mainsfrequency,host=%s freq=%f %llu\n", influxTag, f, tt);
int c = sprintf(tmpBuf, "mainsfrequency,host=%s,valid=%d,location=%s "
"period=%u,freq=%f,freqSmoothed=%f,gradient=%f,freqRaw=%f "
"%llu\n",
influxTag, valid, location,
period, fSmoothed, fSmoothed, gradient, fRaw,
tt);
if ((bufferNextEntry + c + 10) > (influxBuffer + BUFSIZE)) {
influxSendRequest();
influxClearBuffer();
totalEntries += entries;
fprintf(stderr, "%u entries sent to database, in total %u, skipped: %u\n", entries, totalEntries, skipped);
entries = 0;
if ((influxBuffers[PERIOD_20MS]->nextEntry + c + 10) > (influxBuffers[PERIOD_20MS]->buffer + BUFSIZE)) {
influxSendRequest(influxBuffers[PERIOD_20MS]);
influxBuffers[PERIOD_20MS]->totalEntries += influxBuffers[PERIOD_20MS]->entries;
logmsg(LOG_INFO, "%u 20ms-entries sent to database, in total %u, invalid: %u\n",
influxBuffers[PERIOD_20MS]->entries, influxBuffers[PERIOD_20MS]->totalEntries, skipped);
influxClearBuffer(influxBuffers[PERIOD_20MS], false);
}
memcpy(bufferNextEntry, tmpBuf, c);
bufferNextEntry += c;
entries++;
memcpy(influxBuffers[PERIOD_20MS]->nextEntry, tmpBuf, c);
influxBuffers[PERIOD_20MS]->nextEntry += c;
influxBuffers[PERIOD_20MS]->entries += 1;
summedUpTime += period;
divider += 1;
if (divider == ONE_SECOND_DIVIDER) {
double freq1S = ((double)ONE_SECOND_DIVIDER) / (((double)summedUpTime) / 1000000.0);
logmsg(LOG_DEBUG, "%llu: %u %f\n", tt, summedUpTime, freq1S);
int c = sprintf(tmpBuf, "mainsfrequency1S,host=%s,location=%s "
"freq=%f "
"%llu\n",
influxTag, location,
freq1S,
tt);
//if ((influxBuffers[PERIOD_1S]->nextEntry + c + 10) > (influxBuffers[PERIOD_1S]->buffer + BUFSIZE)) {
if (influxBuffers[PERIOD_1S]->entries == 30) {
influxSendRequest(influxBuffers[PERIOD_1S]);
influxBuffers[PERIOD_1S]->totalEntries += influxBuffers[PERIOD_1S]->entries;
logmsg(LOG_INFO, "%u 1s-entries sent to database, in total %u\n",
influxBuffers[PERIOD_1S]->entries, influxBuffers[PERIOD_1S]->totalEntries);
influxClearBuffer(influxBuffers[PERIOD_1S], false);
}
memcpy(influxBuffers[PERIOD_1S]->nextEntry, tmpBuf, c);
influxBuffers[PERIOD_1S]->nextEntry += c;
influxBuffers[PERIOD_1S]->entries += 1;
divider = 0;
summedUpTime = 0.0;
}
}

View File

@ -3,7 +3,7 @@
#include <libconfig.h>
void influxAddFrequency(double f);
void influxAddFrequency(uint32_t period, double fRaw, double fSmoothed, double gradient, int valid);
void influxInit(config_t *pCfg);
#endif // _INFLUX_H_
#endif // _INFLUX_H_

13
src/logging.c Normal file
View File

@ -0,0 +1,13 @@
#include <syslog.h>
#include <stdarg.h>
void logmsg(int prio, const char* format, ...) {
va_list vl;
openlog("counter", 0, LOG_LOCAL0);
va_start(vl, format);
vsyslog(prio, format, vl);
va_end(vl);
closelog();
}

8
src/logging.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef _LOGGING_H_
#define _LOGGING_H_
#include <syslog.h>
void logmsg(int prio, const char* format, ...);
#endif // _LOGGING_H_

6
src/version.c Normal file
View File

@ -0,0 +1,6 @@
#include <stdint.h>
const uint32_t REFCNT = D_REFCNT;
const char VERSION[] = D_VERSION;