[vz-users] 1 wirevz startet nicht

Udo1 udo1 at gmx.net
Sun Jan 26 11:47:29 CET 2014


Am 26.01.2014 10:19, schrieb Timo Giesen:
> @ Udo: Wenn es nicht klappt, würde ich gerne auf dein Angebot zurück kommen.
Ja, kein Problem.

Ich bin mir nicht sicher ob die letzte 1wirevz-Änderung 
(Temperaturmessung ging nicht unter -10°C ) richtig in github umgesetzt 
wurde, deshalb hänge ich mal hier die funktionierende Version von 
1wirevz.c  an.

Gruß
Udo
-------------- next part --------------
/**************************************************************************

DS2482 I²C 1-Wire® Master to Volkszaehler 'RaspberryPI deamon'.

https://github.com/w3llschmidt/1wirevz.git

Henrik Wellschmidt  <w3llschmidt at gmail.com>

**************************************************************************/

#define DAEMON_NAME "1wirevz"
#define DAEMON_VERSION "1.5"
#define DAEMON_BUILD "1"

/**************************************************************************

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.

**************************************************************************/

#include <stdio.h>              /* standard library functions for file input and output */
#include <stdlib.h>             /* standard library for the C programming language, */
#include <string.h>             /* functions implementing operations on strings  */
#include <unistd.h>             /* provides access to the POSIX operating system API */
#include <sys/stat.h>           /* declares the stat() functions; umask */
#include <fcntl.h>              /* file descriptors */
#include <syslog.h>             /* send messages to the system logger */
#include <errno.h>              /* macros to report error conditions through error codes */
#include <signal.h>             /* signal processing */
#include <stddef.h>             /* defines the macros NULL and offsetof as well as the types ptrdiff_t, wchar_t, and size_t */
#include <dirent.h>		/* constructs that facilitate directory traversing */

#include <libconfig.h>          /* reading, manipulating, and writing structured configuration files */
#include <curl/curl.h>          /* multiprotocol file transfer library */

void daemonShutdown();
void signal_handler(int sig);
void daemonize(char *rundir, char *pidfile);

int pidFilehandle, minterval, vzport, i, count;

const char *vzserver, *vzpath, *uuid;

char sensorid[3][32][17], vzuuid[3][32][64], crc_buffer[64], temp_buffer[64], fn[128], url[128];

char crc_ok[] = "YES";
char not_found[] = "not found.";

double temp;

config_t cfg;

void signal_handler(int sig) {
	switch(sig)
	{
		case SIGHUP:
		syslog(LOG_WARNING, "Received SIGHUP signal.");
		break;
		case SIGINT:
		case SIGTERM:
		syslog(LOG_INFO, "Daemon exiting");
		daemonShutdown();
		exit(EXIT_SUCCESS);
		break;
		default:
		syslog(LOG_WARNING, "Unhandled signal %s", strsignal(sig));
		break;
	}
}

void  daemonShutdown() {
		close(pidFilehandle);
		remove("/tmp/1wirevz.pid");
}

void daemonize(char *rundir, char *pidfile) {
	int pid, sid, i;
	char str[10];
	struct sigaction newSigAction;
	sigset_t newSigSet;

	if (getppid() == 1)
	{
		return;
	}

	sigemptyset(&newSigSet);
	sigaddset(&newSigSet, SIGCHLD);
	sigaddset(&newSigSet, SIGTSTP);
	sigaddset(&newSigSet, SIGTTOU);
	sigaddset(&newSigSet, SIGTTIN);
	sigprocmask(SIG_BLOCK, &newSigSet, NULL);

	newSigAction.sa_handler = signal_handler;
	sigemptyset(&newSigAction.sa_mask);
	newSigAction.sa_flags = 0;

	sigaction(SIGHUP, &newSigAction, NULL);
	sigaction(SIGTERM, &newSigAction, NULL);
	sigaction(SIGINT, &newSigAction, NULL);

	pid = fork();

	if (pid < 0)
	{
		exit(EXIT_FAILURE);
	}

	if (pid > 0)
	{
		printf("Child process created: %d\n", pid);
		exit(EXIT_SUCCESS);
	}
	
	//umask(027);

	sid = setsid();
	if (sid < 0)
	{
		exit(EXIT_FAILURE);
	}

	for (i = getdtablesize(); i >= 0; --i)
	{
		close(i);
	}

	close(STDIN_FILENO);
	close(STDOUT_FILENO);
	close(STDERR_FILENO);

	chdir(rundir);

	pidFilehandle = open(pidfile, O_RDWR|O_CREAT, 0600);

	if (pidFilehandle == -1 )
	{
		syslog(LOG_INFO, "Could not open PID lock file %s, exiting", pidfile);
		exit(EXIT_FAILURE);
	}

	if (lockf(pidFilehandle,F_TLOCK,0) == -1)
	{
		syslog(LOG_INFO, "Could not lock PID lock file %s, exiting", pidfile);
		exit(EXIT_FAILURE);
	}

	sprintf(str,"%d\n",getpid());

	write(pidFilehandle, str, strlen(str));
}

void cfile() {

	config_init(&cfg);

	int chdir(const char *path);

	chdir ("/etc");

	if(!config_read_file(&cfg, DAEMON_NAME".cfg"))
	{
		syslog(LOG_INFO, "Config error > /etc/%s - %s\n", config_error_file(&cfg),config_error_text(&cfg));
		config_destroy(&cfg);
		daemonShutdown();
		exit(EXIT_FAILURE);
	}

	if (!config_lookup_string(&cfg, "vzserver", &vzserver))
	{
		syslog(LOG_INFO, "Missing 'VzServer' setting in configuration file.");
		config_destroy(&cfg);
		daemonShutdown();
		exit(EXIT_FAILURE);
	}
	else
	syslog(LOG_INFO, "VzServer: %s", vzserver);

	if (!config_lookup_int(&cfg, "vzport", &vzport))
	{
		syslog(LOG_INFO, "Missing 'VzPort' setting in configuration file.");
		config_destroy(&cfg);
		daemonShutdown();
		exit(EXIT_FAILURE);
	}
	else
	syslog(LOG_INFO, "VzPort: %d", vzport);


	if (!config_lookup_string(&cfg, "vzpath", &vzpath))
	{
		syslog(LOG_INFO, "Missing 'VzPath' setting in configuration file.");
		config_destroy(&cfg);
		daemonShutdown();
		exit(EXIT_FAILURE);
	}
	else
	syslog(LOG_INFO, "VzPath: %s", vzpath);

	if (!config_lookup_int(&cfg, "interval", &minterval))
	{
		syslog(LOG_INFO, "Missing 'Interval' setting in configuration file.");
		config_destroy(&cfg);
		daemonShutdown();
		exit(EXIT_FAILURE);
	}
	else
	syslog(LOG_INFO, "Metering interval: %d sec", minterval);

}

int count_i2cdevices() {

	int i2cdevices = 0;
	DIR * dirp;
	struct dirent * entry;

	dirp = opendir("/sys/bus/i2c/devices/");
	if (!dirp) {
		syslog ( LOG_INFO, "Error: /sys/bus/i2c/devices not found! Check kernelmodul!" );
		daemonShutdown();
	}	


		while ((entry = readdir(dirp)) != NULL) {
			if (entry->d_type == DT_LNK) {
			i2cdevices++;
			}

		}

	closedir(dirp);

return i2cdevices-2;
}

void ds1820init() {

	int i = 0;
	for (i=1; i<=count_i2cdevices(); i++) {

		char fn[64];
		sprintf ( fn, "/sys/bus/w1/devices/w1_bus_master%d/w1_master_slaves", i );

		FILE *fp;	
		if  ( (fp = fopen ( fn, "r" )) == NULL ) {
		syslog(LOG_INFO, "%s", strerror(errno));					
		}
		else
		{
			count = 1;
			
			while ( fgets ( sensorid[i][count], sizeof(sensorid[i][count]), fp ) != NULL ) {
			sensorid[i][count][strlen(sensorid[i][count])-1] = '\0';
			
				if ( ! ( strstr ( sensorid[i][count], not_found ) )) {
				
					char buffer[32];
					sprintf ( buffer, "*%s", sensorid[i][count] );
					if ( config_lookup_string( &cfg, buffer, &uuid ) == CONFIG_TRUE )
					strcpy(vzuuid[i][count], uuid);
				
				}
						
			if ( ! ( strstr ( sensorid[i][count], not_found ) )) {
			syslog( LOG_INFO, "%s (Bus: %d) (VzUUID: %s)", sensorid[i][count], i, vzuuid[i][count] );
			}
			
			count++;
			}
			
		}
		
	if (fp != NULL)
		fclose ( fp );
	}
	
}
 
void http_post( double temp, char  *vzuuid ) {

	CURL *curl;
	CURLcode curl_res;
 
	sprintf ( url, "http://%s:%d/%s/data/%s.json?value=%.2f", vzserver, vzport, vzpath, vzuuid, temp );

	curl_global_init(CURL_GLOBAL_ALL);

	curl = curl_easy_init();

	if(curl)
	{ 

		FILE* devnull = NULL;
		devnull = fopen("/dev/null", "w+");

		curl_easy_setopt(curl, CURLOPT_USERAGENT, DAEMON_NAME " " DAEMON_VERSION ); 
		curl_easy_setopt(curl, CURLOPT_URL, url);
		curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "");
		
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, devnull);
	
		if( (curl_res  = curl_easy_perform(curl)) != CURLE_OK) {
		syslog ( LOG_INFO, "HTTP_POST(): %s", curl_easy_strerror(curl_res) );
		}
	
		curl_easy_cleanup(curl);
		fclose ( devnull );
		
	}

curl_global_cleanup();
}

double ds1820read(char *sensorid) {

	FILE *fp;	

	sprintf(fn, "/sys/bus/w1/devices/%s/w1_slave", sensorid );

	if  ( (fp = fopen ( fn, "r"  )) == NULL ) {
	return(-1);
	}
	
	else 
	
	{ 
	
		fgets( crc_buffer, sizeof(crc_buffer), fp );
		if ( !strstr ( crc_buffer, crc_ok ) ) 
	 	{
		
			syslog(LOG_INFO, "CRC check failed, SensorID: %s", sensorid);
			
		fclose ( fp );
		return(-1);
		}
		
		else 
		
		{ 
		
		fgets( temp_buffer, sizeof(temp_buffer), fp );
		fgets( temp_buffer, sizeof(temp_buffer), fp );
		
			char *pos = strstr(temp_buffer, "t=");
			if (pos == NULL)
				return -1;
			pos += 2;
			temp = atof(pos)/1000;
			
		fclose ( fp );
		http_post(temp, vzuuid[i][count]);

		}

	}
	
}

int main() { 

    freopen( "/dev/null", "r", stdin);
    freopen( "/dev/null", "w", stdout);
    freopen( "/dev/null", "w", stderr);

	setlogmask(LOG_UPTO(LOG_INFO));
	openlog(DAEMON_NAME, LOG_CONS | LOG_PERROR, LOG_USER);

	syslog(LOG_INFO, "DS2482 I²C 1-Wire® Master to Volkszaehler deamon %s (%s) %d", DAEMON_VERSION, DAEMON_BUILD, count_i2cdevices());

	cfile();
	
	ds1820init();
	
	char pid_file[16];
	sprintf ( pid_file, "/tmp/%s.pid", DAEMON_NAME );
	daemonize( "/tmp/", pid_file );
				
	while(1) {
	
			i = 0;
			for (i=1; i<=count_i2cdevices(); i++) {
			
				sprintf ( fn, "/sys/bus/w1/devices/w1_bus_master%d/w1_master_slaves", i );
			
				FILE *fp;	
				if  ( (fp = fopen ( fn, "r" )) == NULL )
				{
				syslog(LOG_INFO, "%s", strerror(errno));
				}
				else
				{
				
					count = 1;
					while ( fgets ( sensorid[i][count], sizeof(sensorid[i][count]), fp ) != NULL ) {
					sensorid[i][count][strlen(sensorid[i][count])-1] = '\0';
					
						if ( !( strstr ( sensorid[i][count], not_found ) )) {
						ds1820read(sensorid[i][count]);
						
						}

					count++;
					}
					
				}
				
			if (fp != NULL)
				fclose ( fp );	
			}
			
	sleep(minterval);
	}
	
return(0);
}


More information about the volkszaehler-users mailing list