Compare commits
20 Commits
DropPeaks
...
SecondValu
Author | SHA1 | Date | |
---|---|---|---|
59e3350aaf | |||
6c21983917 | |||
80103312ce | |||
9213cfac11 | |||
07c80eb21c | |||
eb83c754bf | |||
4f81343a89 | |||
e8102e74a9 | |||
784346b833 | |||
e3ee3a08e8 | |||
5ef114b634 | |||
2dd586d7e4 | |||
5d1f7dde89 | |||
8d56c5aff4 | |||
5230139544 | |||
08c76f13de | |||
6a13da024d
|
|||
8c0c864905 | |||
61b1498d7b | |||
e21e114313 |
42
src/Makefile
42
src/Makefile
@ -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
1
src/VERSION
Normal file
@ -0,0 +1 @@
|
||||
0.97
|
@ -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,7 +56,7 @@ 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",
|
||||
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);
|
||||
@ -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();
|
||||
uint32_t period = ringbufferGet();
|
||||
|
||||
double f = 1.0 / (((double) diff) / 1000000.0);
|
||||
double fRaw = 1.0 / (((double) period) / 1000000.0);
|
||||
int valid = settled ? 1 : 0;
|
||||
|
||||
if (settled && (abs(f - lastF) > epsilon)) {
|
||||
printf("Current f=%f, last f=%f, gradient too large, skipped\n", f, lastF);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
119
src/influx.c
119
src/influx.c
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -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_
|
13
src/logging.c
Normal file
13
src/logging.c
Normal 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
8
src/logging.h
Normal 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
6
src/version.c
Normal file
@ -0,0 +1,6 @@
|
||||
#include <stdint.h>
|
||||
|
||||
const uint32_t REFCNT = D_REFCNT;
|
||||
const char VERSION[] = D_VERSION;
|
||||
|
||||
|
Reference in New Issue
Block a user