Re: teleinfo linky mode standard
Publié : 31 mars 2021, 18:57
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 :
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¶m=udevice&idx=735&nvalue=0&svalue=";
const char* JSON_HEADER2 = "http://ip_pi:8080/json.htm?type=command¶m=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);
}
