Re: teleinfo linky mode standard
Publié : 14 juil. 2018, 19:25
Bon, finalement j'ai pris ton code qui m'a fait gagné beaucoup de temps. Merci
Chez moi, il plantait régulièrement (il faut dire que j'ai pas mal de lignes en erreur, je pense que mon dongle usb a du mal à suivre).
Donc, j'ai pris ton code, supprimé les trames EAST et SINSTS (qui seront toujours à zéro pour moi) et je le rends à usage unique : il prend 10 secondes pour récupérer 2-3 trames EAIT (total production) + SINSTI (production instantanée) et il s'arrête juste après avoir mis à jour domoticz.
Dans la contable, je lui fais faire une mise à jour toutes les 2 minutes.
Enedis devrait me repasser en mode historique (je ne sais pas si c'est une bonne idée).
ton code saccagé :
Installation Curl sur Raspberry :
Compilation :
Chez moi, il plantait régulièrement (il faut dire que j'ai pas mal de lignes en erreur, je pense que mon dongle usb a du mal à suivre).
Donc, j'ai pris ton code, supprimé les trames EAST et SINSTS (qui seront toujours à zéro pour moi) et je le rends à usage unique : il prend 10 secondes pour récupérer 2-3 trames EAIT (total production) + SINSTI (production instantanée) et il s'arrête juste après avoir mis à jour domoticz.
Dans la contable, je lui fais faire une mise à jour toutes les 2 minutes.
Enedis devrait me repasser en mode historique (je ne sais pas si c'est une bonne idée).
ton code saccagé :
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/ttyUSB0";
const speed_t BAUD_RATE = B9600;
const char DEMILITER = 0x09;
const char* JSON_HEADER = "http://192.168.1.40:8080/json.htm?type=command¶m=udevice&idx=735&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);
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);
}
Code : Tout sélectionner
sudo apt-get install libcurl4-openssl-devCode : Tout sélectionner
sudo cc driver_teleinfo.c -lcurl