teleinfo linky mode standard

Forum pour tous les autres objets : sondes météo, capteurs, actionneurs ...
Vous avez un besoin mais vous ne savez pas quel matériel choisir ? C'est ici.
js-martin
Messages : 487
Inscription : 22 mars 2015, 22:08
Contact :

Re: teleinfo linky mode standard

Message par js-martin »

J'ai retrouvé mes dernières sources avant compilation !

C'est plus logique ; ce code alimente les 2 widgets !

Ca va aller mieux avec cela :

Code : Tout sélectionner

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <limits.h>
#include <sys/time.h>
#include <curl/curl.h>


//--------------------------------------------------
// DONNEES A MODIFIER EN FONCTION DE LA CONFIGURATION SOUHAITEE
//--------------------------------------------------
// Port Serie et Baud Rate
// Délimiteur (normalement 0x09 à 9600 bauds et 0x20 à 1200 bauds)
// Requête JSON pour Domoticz (CHANGER LE IDX AVEC LE NUMERO DE DEVICE)
//--------------------------------------------------
const char* SERIAL_PORT = "/dev/ttyUSBP";
const speed_t BAUD_RATE = B9600;
const char DEMILITER = 0x09;
const char* JSON_HEADER = "http://ip_pi:8080/json.htm?type=command&param=udevice&idx=735&nvalue=0&svalue=";
const char* JSON_HEADER2 = "http://ip_pi:8080/json.htm?type=command&param=udevice&idx=745&nvalue=0&svalue=";
//--------------------------------------------------



/* Number of consecutive characters to read (max = 255) */
const unsigned int BUFFER_SIZE = 255;
/* Max number of characters in one line (<= BUFFER SIZE) */
const unsigned int MAX_LINE_SIZE = 150;
/* Min number of characters in one line (<= MAX_LINE_SIZE) */
const unsigned int MIN_LINE_SIZE = 5;

typedef struct {
	unsigned int EAST;
	unsigned int EAIT;
	unsigned int SINSTS;
	unsigned int SINSTI;
} Teleinfo;

typedef struct {
	int value;
	unsigned int elapsed_seconds;
} DomoticzDevice;


Teleinfo teleinfo = { .EAST = 0, .EAIT = 0, .SINSTS = 0, .SINSTI = 0 };
DomoticzDevice EDF = { .value = 0, .elapsed_seconds = 0 };

unsigned int send_message = 0; 
struct timeval tv1; struct timezone tz1;
struct timeval tv2; struct timezone tz2;

int set_interface_attribs(int fd, int speed)
{
    struct termios tty;

    if (tcgetattr(fd, &tty) < 0)
    {
        printf("Error from tcgetattr: %s\n", strerror(errno));
        return -1;
    }

    cfsetospeed(&tty, (speed_t)speed);
    cfsetispeed(&tty, (speed_t)speed);

    tty.c_cflag |= (CLOCAL | CREAD);    /* ignore modem controls */
    tty.c_cflag &= ~CSIZE;
    tty.c_cflag |= CS7;         /* 7-bit characters */
    tty.c_cflag |= PARENB;     /* parity enabled & even */
    tty.c_cflag &= ~CSTOPB;     /* 1 stop bit */
    tty.c_cflag &= ~CRTSCTS;    /* no hardware flowcontrol */

    /* setup for non-canonical mode */
    tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
    tty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
    tty.c_oflag &= ~OPOST;

    /* read characters, with max delay of half second to receive a char */
    tty.c_cc[VMIN] = BUFFER_SIZE;
    tty.c_cc[VTIME] = 5;

    if (tcsetattr(fd, TCSANOW, &tty) != 0) 
    {
        printf("Error from tcsetattr: %s\n", strerror(errno));
        return -1;
    }
    return 0;
}

int isCheckSumOk(char* line)
{
	unsigned int checksum_expected = 0;
	unsigned int checksum_real = 0;
	unsigned int i;

	checksum_expected = line[strlen(line) - 1];
	for (i = 0; i <= strlen(line) - 2; i++)
	{
		checksum_real += line[i];
	}
	checksum_real = (checksum_real & 0x3F) + 0x20;

	if (checksum_expected != checksum_real)
	{
		//printf("ERROR --> Checksum failed on line: \"%s\"\n", line);
		unsigned char *p;
		unsigned int linelen = strlen(line);
		for (p = line; linelen-- > 0; p++)
			//printf(" 0x%x", *p);
		//printf("\n");
		return -1;
	}

	return 0;
}

int strToUL(char* str)
{
	unsigned int val = 0;
	char *endptr;
	errno = 0;
	val = strtoul(str, &endptr, 10);
	if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) || (errno != 0 && val == 0)) 
	{
		printf("ERROR --> Cannot convert to ul the string: \"%s\"\n", str);
		return -1;
	}
	else if (endptr == str)
	{
		printf("ERROR --> Cannot convert to ul an empty string: \"%s\"\n", str);
		return -1;
	}
	return (int)val;
}

int sendUrl(char* url)
{
	int ret = -1;
    CURL *curl;
    CURLcode res;
    curl = curl_easy_init();
    if (curl)
    {
        curl_easy_setopt(curl, CURLOPT_URL, url);
		curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
		curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); //Prevent "longjmp causes uninitialized stack frame" bug
		curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "deflate");
		curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60);
        //curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
        //curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data);
        res = curl_easy_perform(curl);
        if(res != CURLE_OK)
        {
			printf("ERROR --> Cannot send curl url: \"%s\"\n", url);
        }
        else
        {
			ret = 0;
		}

        curl_easy_cleanup(curl);
    }
    else
    {
		printf("ERROR --> Cannot init curl\n");
	}
	return ret;
}

int processLine(char* line)
{
	char label [MAX_LINE_SIZE];
	char elem1 [MAX_LINE_SIZE];
	char elem2 [MAX_LINE_SIZE];
	int val;
	unsigned int start = 0;
	unsigned int i = 0;
	// Find next elem
	label[0] = '\0';
	for (i = start; i <= strlen(line) - 2; i++)
	{
		// Find the delimiter
		if (line[i] == DEMILITER)
		{
			memcpy(label, &line[start], i-start);
			label[i-start] = '\0';
			break;
		}
	}
	// Find next elem
	start = i+1;
	elem1[0] = '\0';
	for (i = start; i <= strlen(line) - 2; i++)
	{
		// Find the delimiter
		if (line[i] == DEMILITER)
		{
			memcpy(elem1, &line[start], i-start);
			elem1[i-start] = '\0';
			break;
		}
	}
	// Find next elem
	start = i+1;
	elem2[0] = '\0';
	for (i = start; i <= strlen(line) - 2; i++)
	{
		// Find the delimiter
		if (line[i] == DEMILITER)
		{
			memcpy(elem2, &line[start], i-start);
			elem2[i-start] = '\0';
			break;
		}
	}

//	printf("DEBUG --> New line: %s - %s - %s\n", label, elem1, elem2);
	// Save value
//	if(strcmp(label, "EAST") == 0) {
//		val = strToUL(elem1);
//		if (val != -1) teleinfo.EAST = (unsigned int)val;
//		else return -1;
//	} else 
        if(strcmp(label, "EAIT") == 0) {
		val = strToUL(elem1);
		if (val != -1) teleinfo.EAIT = (unsigned int)val;
		else return -1;
	}
//	else if(strcmp(label, "SINSTS") == 0) {
//		val = strToUL(elem1);
//		if (val != -1) teleinfo.SINSTS = (unsigned int)val;
//		else return -1;
//	}
	else if(strcmp(label, "SINSTI") == 0) {
		val = strToUL(elem1);
		if (val != -1) teleinfo.SINSTI = (unsigned int)val;
		else return -1;
	}
}

int main()
{
    //freopen("out.txt", "a", stdout);
    int fd;
    int wlen;
    unsigned char line[MAX_LINE_SIZE];
    unsigned int linelen = 0;
    unsigned int pos = 0;
    fd = open(SERIAL_PORT, O_RDONLY | O_NOCTTY | O_SYNC);
    if (fd < 0)
    {
        printf("Error opening %s: %s\n", SERIAL_PORT, strerror(errno));
        return -1;
    }

	/* Get current time */
	gettimeofday(&tv1, &tz1);
	gettimeofday(&tv2, &tz2);

    /* Open serial port */
    set_interface_attribs(fd, BAUD_RATE);

    /* Receive characters */
    do
    {
        unsigned char buf[BUFFER_SIZE];
        int rdlen;
        int first_line = 1;

        rdlen = read(fd, buf, sizeof(buf) - 1);
        if (rdlen > 0)
        {
			int i = 0;
			while (i < rdlen)
			{
				// Discard all special characters
				const char c = buf[i];
				if (((c >= 0x00) && (c <= 0x01)) || ((c >= 0x04) && (c <= 0x08)))
				{
					//printf("DEBUG --> Char 0x%x discarded in line: \"%s\"\n", c, line);
					i++;
					continue;
				}

				// Get character
				line[pos] = c;

				// If line ending is found
				if (((c >= 0x02) && (c <= 0x03)) || ((c >= 0x0a) && (c <= 0x0f)))
				{
					// Close string
					line[pos] = 0;
					linelen = pos;
					pos = 0;

					// Discard first line as it may be truncated
					if (first_line)
					{
						first_line = 0;
					}
					// Discard lines too small
					else if (linelen < MIN_LINE_SIZE)
					{
						// Nothing to do
                        //printf("WARNING --> Line discarded because too small: \"%s\"\n", line);
					}
					// Discard incoherent lines
					else if (line[linelen-2] != DEMILITER)
					{
						//printf("ERROR --> Ending delimiter not found on line: \"%s\"\n", line);
					}
					else
					{
#ifdef DISPLAY_LINE_STRING
						//printf("Read %d: \"%s\"\n", linelen, line);
#endif
#ifdef DISPLAY_LINE_HEX
						unsigned char *p;
						//printf("Read %d:", linelen);
						for (p = line; linelen-- > 0; p++)
							//printf(" 0x%x", *p);
						//printf("\n");
#endif
						// Verify checksum
						if (isCheckSumOk(line) == 0)
						{
							//printf("SUCCESS --> Checksum OK on line: \"%s\"\n", line);
							processLine(line);
						}
					}
				}

				else if (pos == sizeof(line) - 1)
				{
					// Close string
					line[pos] = 0;
					linelen = pos;
					pos = 0;

					printf("ERROR: no new line read in line: \"%s\"\n", line);
				}

				else if (pos == sizeof(buf) - 1)
				{
					// Close string
					line[pos] = 0;
					linelen = pos;
					pos = 0;

					printf("ERROR: no new line read in buffer: \"%s\"\n", buf);
				}

				else
				{
					pos++;
				}

				i++;
			}

#ifdef DISPLAY_BUFFER_STRING
            buf[rdlen] = 0;
            printf("Read %d: \"%s\"\n", rdlen, buf);
#endif
#ifdef DISPLAY_BUFFER_HEX
            unsigned char *p;
            printf("Read %d:", rdlen);
            for (p = buf; rdlen-- > 0; p++)
                printf(" 0x%x", *p);
            printf("\n");
#endif
        }
        else if (rdlen < 0)
        {
            printf("Error from read: %d: %s\n", rdlen, strerror(errno));
        }


		/* Check if it's time to send a message to Domoticz */
		if (send_message)
		{
			send_message = 0;

			//Calculate values to send
			//int SINST = (int)(teleinfo.SINSTS) - (int)(teleinfo.SINSTI);
                        int SINST =  (int)(teleinfo.SINSTI);
			char SINST_str[12]; sprintf(SINST_str, "%d", SINST);

			//int EAT = (int)(teleinfo.EAST) - (int)(teleinfo.EAIT);
                        int EAT =  (int)(teleinfo.EAIT);
			char EAT_str[12]; sprintf(EAT_str, "%d", EAT);

			//Construction of message to send
			char message [1000];
			strcpy(message, JSON_HEADER);
			strcat(message, SINST_str);
			strcat(message, ";");
			strcat(message, EAT_str);
			//Send message
			if(sendUrl(message) == 0)
			{
			//	printf("DEBUG --> New message sent: \"%s\"\n", message);
                        }

                        //Construction of second message to send
                        char message2 [1000];
                        strcpy(message2, JSON_HEADER2);
                        strcat(message2, EAT_str);
                        strcat(message2, ";0;0;0;");
                        strcat(message2, SINST_str);
                        strcat(message2, ";0");
                        //Send message
                        if(sendUrl(message2) == 0)
                        {
                        //        printf("DEBUG --> New message sent: \"%s\"\n", message2);
                                exit(0);
                        }

		}
		else
		{
			gettimeofday(&tv2, &tz2);
			if((tv2.tv_sec - tv1.tv_sec) >= 10)
			{
				send_message = 1;
				tv1.tv_sec = tv2.tv_sec;
			}
		}

        /* sleep and repeat read */
        //sleep(1);
    } while (1);
}


Domotisation de : mes compteurs EDF, solaire, eau / mon alarme / ma Chaudière Viessamnn / mon congel / ma sonnette. Matériels : Pi2 - RFXTrx433e - Zwave+ Aeotec, ampoules Hue - Détecteur et prises Fibaro - Capteurs Oregon - présentation installation => lien
knasson
Messages : 245
Inscription : 26 mars 2021, 08:59

Re: teleinfo linky mode standard

Message par knasson »

merci encore , ton code l'essayer c'est l'adopter!
Pour le moment je ne vois pas ce que m'apporte le second compteur virtuel, sur les 2 compteurs j'ai les même valeurs...
je remarque que ton dashboard est diffèrent du mien..?
Comment eviter les zéros que je reçois de temps en temps? comme si l'acquisition se faisait mal! (pas assez rapide?)
Capture d’écran 2021-04-01 173407.jpg
Capture d’écran 2021-04-01 173407.jpg (98.93 Kio) Consulté 6152 fois
@ plus
Knasson
js-martin
Messages : 487
Inscription : 22 mars 2015, 22:08
Contact :

Re: teleinfo linky mode standard

Message par js-martin »

Je n’ai pas ce symptôme avec le même code :
EBA644A1-712D-416E-B131-E359219F4C73.jpeg
EBA644A1-712D-416E-B131-E359219F4C73.jpeg (417.37 Kio) Consulté 6149 fois
Peut-être que tu as des lectures incorrectes (cable trop long ?)

En tout cas, ça progresse :D
Domotisation de : mes compteurs EDF, solaire, eau / mon alarme / ma Chaudière Viessamnn / mon congel / ma sonnette. Matériels : Pi2 - RFXTrx433e - Zwave+ Aeotec, ampoules Hue - Détecteur et prises Fibaro - Capteurs Oregon - présentation installation => lien
knasson
Messages : 245
Inscription : 26 mars 2021, 08:59

Re: teleinfo linky mode standard

Message par knasson »

moi j'ai le module microTeleinfo de hallard.me que j'ai acheté sur Tindie et qui a été adapté a ce compteur,
quelques résistances ont dues être changées.
Image
peut être que ce module n'est pas assez rapide ou assez fiable.
quel est ton interface?
merci de ton accompagnement et de tes encouragements...
knasson
Messages : 245
Inscription : 26 mars 2021, 08:59

Re: teleinfo linky mode standard

Message par knasson »

j'ai eu un ou 2 messages "undervoltage" sur le RPI qui semblaient perturber pas mal le fonctionnement du ssh et du raspberrypi.
faut dire , j'ai un disque dur connecté sur l'USB sur le RPI.
je crains que l'alim USB soit un peu insuffisante...j'ai donc débranché tout sauf le disque dur (ecran , dongle clavier) je vais voir ce que ca donne. Sinon j'ai 2 pistes
-renforcer l'alim 5V (mais j'ai encore des zéros ) prendre une 2,5 ou 3 A si je trouve
-changer d'interface USB et prendre le "cartelectronic"?

Merci pour vos conseils,

Bonne journée,

Jean-Claude dit Knasson
js-martin
Messages : 487
Inscription : 22 mars 2015, 22:08
Contact :

Re: teleinfo linky mode standard

Message par js-martin »

J'utilise ces convertisseurs bas de gamme :

PL2303HX UART Board USB to RS232 Serial TTL Convertisseur
Domotisation de : mes compteurs EDF, solaire, eau / mon alarme / ma Chaudière Viessamnn / mon congel / ma sonnette. Matériels : Pi2 - RFXTrx433e - Zwave+ Aeotec, ampoules Hue - Détecteur et prises Fibaro - Capteurs Oregon - présentation installation => lien
knasson
Messages : 245
Inscription : 26 mars 2021, 08:59

Re: teleinfo linky mode standard

Message par knasson »

Bas de gamme par le prix mais semble t il avec une base de temps réglée par quartz donc me parait pas si mal!
j'en ai commandé un...on verra bien.
par ailleurs je vais vérifier mon alim 5V.J'en ai une autre de 5,3 V et 2 A .
A voir je cherche...j'ai toujours des passages par zero assez nombreux!
Pièces jointes
Capture d’écran 2021-04-02 162324.jpg
Capture d’écran 2021-04-02 162324.jpg (82.92 Kio) Consulté 6102 fois
knasson
Messages : 245
Inscription : 26 mars 2021, 08:59

Re: teleinfo linky mode standard

Message par knasson »

Indice c'est surtout l'après midi...est ce lié a la température, aux effets d'ombrage de proximité?
c'est juste pour le fun car ca ,n'influence pas la production journalière...(qui est fonction du compteur totalisateur). :roll:
Ne serait il pas possible de modifier le code pour attendre la prochaine valeur non nulle? Comme je ne connais rien en C++
je ne vais pas me lancer la dedans. Mais j'en ai envie! ;)
js-martin
Messages : 487
Inscription : 22 mars 2015, 22:08
Contact :

Re: teleinfo linky mode standard

Message par js-martin »

Juste pour voir : tu peux mettre la fréquence dans la contab à 5 min ?
Domotisation de : mes compteurs EDF, solaire, eau / mon alarme / ma Chaudière Viessamnn / mon congel / ma sonnette. Matériels : Pi2 - RFXTrx433e - Zwave+ Aeotec, ampoules Hue - Détecteur et prises Fibaro - Capteurs Oregon - présentation installation => lien
knasson
Messages : 245
Inscription : 26 mars 2021, 08:59

Re: teleinfo linky mode standard

Message par knasson »

oui je fais ca,
j'ai remarqué que les envois vers la base de donnée se font toutes les 5 minutes, tu pense a des conflits d'accès!
ok je fais et on voit...
Merci
Répondre