Initial commit on github.

This commit is contained in:
Roland Jax
2013-11-14 21:15:14 +01:00
parent 36fc9f23c2
commit 916ec20456
37 changed files with 8561 additions and 2 deletions
+11
View File
@@ -0,0 +1,11 @@
noinst_LIBRARIES = libebus.a liblog.a
libebus_a_SOURCES = ebus-decode.c ebus-decode.h \
ebus-cmd.c ebus-cmd.h \
ebus-bus.c ebus-bus.h
liblog_a_SOURCES = log.c log.h
distclean-local:
-rm -f Makefile.in
+1195
View File
File diff suppressed because it is too large Load Diff
+325
View File
@@ -0,0 +1,325 @@
/*
* Copyright (C) Roland Jax 2012-2013 <roland.jax@liwest.at>
*
* This file is part of ebusd.
*
* ebusd 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.
*
* ebusd 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 ebusd. If not, see http://www.gnu.org/licenses/.
*/
/**
* @file ebus-bus.h
* @brief ebus communication functions
* @author roland.jax@liwest.at
* @version 0.1
*/
#ifndef EBUS_BUS_H_
#define EBUS_BUS_H_
#include <sys/time.h>
#include "ebus-common.h"
#define TMP_BUFSIZE 1024
/**
* @brief sending data structure
*/
struct send_data {
unsigned char crc; /**< crc of escaped message */
unsigned char msg[SERIAL_BUFSIZE + 1]; /**< original message */
int len; /**< length of original message */
unsigned char msg_esc[SERIAL_BUFSIZE + 1]; /**< esacaped message */
int len_esc; /**< length of esacaped message */
};
/**
* @brief receiving data structure
*/
struct recv_data {
unsigned char crc_recv; /**< received crc */
unsigned char crc_calc; /**< calculated crc */
unsigned char msg[SERIAL_BUFSIZE + 1]; /**< unescaped message */
int len; /**< length of unescaped message */
unsigned char msg_esc[SERIAL_BUFSIZE + 1]; /**< received message */
int len_esc; /**< length of received message */
};
/**
* @brief set rawdump
* @param [in] YES | NO
* @return none
*/
void eb_set_rawdump(int dump);
/**
* @brief set showraw
* @param [in] YES | NO
* @return none
*/
void eb_set_showraw(int show);
/**
* @brief set own ebus address
* @param [in] src ebus address
* @return none
*/
void eb_set_qq(unsigned char src);
/**
* @brief set number of retry to get bus
* @param [in] retry
* @return none
*/
void eb_set_get_retry(int retry);
/**
* @brief set number of skipped SYN if an error occurred while getting the bus
* @param [in] skip is only the start value (skip = skip_ack + retry;)
* @return none
*/
void eb_set_skip_ack(int skip);
/**
* @brief set max wait time between send and receive of own address (QQ)
* @param [in] usec wait time in usec
* @return none
*/
void eb_set_max_wait(long usec);
/**
* @brief set number of retry to send message
* @param [in] retry
* @return none
*/
void eb_set_send_retry(int retry);
/**
* @brief set number of printed hex bytes
* @param [in] size
* @return none
*/
void eb_set_print_size(int size);
/**
* @brief calculate delte time of given time stamps
* @param [in] *tact newer time stamp
* @param [in] *tlast older time stamp
* @param [out] *tdiff calculated time difference
* @return 0 positive | -1 negative ??? lol
*/
int eb_diff_time(const struct timeval *tact, const struct timeval *tlast, struct timeval *tdiff);
/**
* @brief Open a file in write mode.
* @param [in] *file device
* @return 0 ok | -1 error
*/
int eb_raw_file_open(const char *file);
/**
* @brief close a file.
* @return 0 ok | -1 error
*/
int eb_raw_file_close(void);
/**
* @brief write bytes into file
* @param [in] *buf pointer to a byte array
* @param [in] buflen length of byte array
* @return 0 ok | -1 error
*/
int eb_raw_file_write(const unsigned char *buf, int buflen);
/**
* @brief Check if serial FD is vaild.
* @return 0 ok | -1 error
*/
int eb_serial_valid();
/**
* @brief Open serial device in raw mode. 1 Byte is then minimum input length.
* @param [in] *dev serial device
* @param [out] *fd file descriptor from opened serial device
* @return 0 ok | -1 error
*/
int eb_serial_open(const char *dev, int *fd);
/**
* @brief close serial device and set settings to default.
* @return 0 ok | -1 error | -2 bad file descriptor
*/
int eb_serial_close(void);
/**
* @brief send bytes to serial device
* @param [in] *buf pointer to a byte array
* @param [in] buflen length of byte array
* @return 0 ok | -1 error | -2 bad file descriptor
*/
int eb_serial_send(const unsigned char *buf, int buflen);
/**
* @brief receive bytes from serial device
* @param [out] *buf pointer to a byte array received bytes
* @param [out] *buflen length of received bytes
* @return 0 ok | -1 error | -2 bad file descriptor | -3 received data > BUFFER
*/
int eb_serial_recv(unsigned char *buf, int *buflen);
/**
* @brief print received results in a specific format
* @return none
*/
void eb_print_result(void);
/**
* @brief print received data with hex format
* @param [in] *buf pointer to a byte array of received bytes
* @param [in] buflen length of received bytes
* @return none
*/
void eb_print_hex(const unsigned char *buf, int buflen);
/**
* @brief get received data
* @param [out] *buf pointer to a byte array of received bytes
* @param [out] *buflen length of received bytes
* @return none
*/
void eb_recv_data_get(unsigned char *buf, int *buflen);
/**
* @brief prepare received data
* @param [in] *buf pointer to a byte array of received bytes
* @param [in] buflen length of received bytes
* @return none
*/
void eb_recv_data_prepare(const unsigned char *buf, int buflen);
/**
* @brief receive bytes from serial device
* @param [out] *buf pointer to a byte array of received bytes
* @param [out] buflen length of received bytes
* @return 0 ok | -1 error | -2 syn no answer from slave
* | -3 SYN received after answer from slave
*/
int eb_recv_data(unsigned char *buf, int *buflen);
/**
* @brief receive bytes from serial device until SYN byte was received
* @param [in] *skip number skipped SYN bytes
* @return 0 ok | -1 error
*/
int eb_bus_wait_syn(int *skip);
/**
* @brief try to get bus for sending
* \li wait SYN byte, send our ebus address and wait for minimun of ~4200 usec
* \li read at least one byte and compare it with sent byte.
* @return 0 ok | -1 error | 1 max retry was reached
*/
int eb_bus_wait(void);
/**
* @brief free bus after syn was sent
* @return 0 ok | -1 error
*/
int eb_bus_free(void);
/**
* @brief receive ACK byte from serial device
* @param [out] *buf pointer to a byte array of received bytes
* @param [out] buflen length of received bytes
* @return 0 ok | 1 negative ACK | -1 error | -2 send and recv msg are different
* | -3 syn received (no answer from slave) | -4 we should never reach this
*/
int eb_send_data_get_ack(unsigned char *buf, int *buflen);
/**
* @brief prepare send data
* @param [in] *buf pointer to a byte array of send bytes
* @param [in] buflen length of send bytes
* @return none
*/
void eb_send_data_prepare(const unsigned char *buf, int buflen);
/**
* @brief handle sending ebus data
*
* \li Given input data will be prepared (escape, crc) and send to ebus.
* \li Answer will be received, prepared (unescape, crc) and return as result.
*
* @param [in] *buf pointer to a byte array
* @param [in] buflen length of byte array
* @param [in] type is the type of message to send
* @param [out] *bus pointer to answer array
* @param [out] *buslen point to answer length
* @return 0 ok | 1 neg. ACK from Slave | -1 error
*/
int eb_send_data(const unsigned char *buf, int buflen, int type, unsigned char *bus, int *buslen);
/**
* @brief handle send ebus cmd
* @param [in] id is index in command array
* @param [in] *data pointer to data bytes for decode/encode
* @param [out] *buf pointer to answer array
* @param [out] *buflen point to answer length
* @return none
*/
void eb_execute(int id, char *data, char *buf, int *buflen);
/**
* @brief handle one collected message
* @param [in] *buf pointer to a byte array
* @param [in] buflen length of byte array
* @return 0-x msg number of collected msg | -1 msg not found | -2 error
*/
int eb_cyc_data_process(const unsigned char *buf, int buflen);
/**
* @brief handle reading cycle ebus data
* @return 0-x length of collected msg | -1 error
*/
int eb_cyc_data_recv();
#endif /* EBUS_BUS_H_ */
+953
View File
@@ -0,0 +1,953 @@
/*
* Copyright (C) Roland Jax 2012-2013 <roland.jax@liwest.at>
*
* This file is part of ebusd.
*
* ebusd 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.
*
* ebusd 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 ebusd. If not, see http://www.gnu.org/licenses/.
*/
/**
* @file ebus-cmd.c
* @brief ebus command file functions
* @author roland.jax@liwest.at
* @version 0.1
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <errno.h>
#include <dirent.h>
#include "log.h"
#include "ebus-decode.h"
#include "ebus-cmd.h"
static struct cycbuf *cyc = NULL;
static int cyclen = 0;
static struct commands *com = NULL;
static int comlen = 0;
void
eb_cmd_uppercase(char *buf)
{
while (*buf++ != '\0')
*buf = toupper((unsigned char) *buf);
}
int
eb_cmd_check_type(int id, const char *type)
{
if (strncasecmp(com[id].type, type, 3) == 0)
return YES;
else
return NO;
}
int
eb_cmd_get_s_type(int id)
{
return com[id].s_type;
}
void
eb_cmd_set_cyc_buf(int id, const unsigned char *msg, int msglen)
{
int i;
for (i = 0; i < cyclen; i++)
if (cyc[i].id == com[id].id)
break;
memcpy(cyc[i].buf, msg, msglen);
cyc[i].buflen = msglen;
}
void
eb_cmd_get_cyc_buf(int id, unsigned char *msg, int *msglen)
{
int i;
for (i = 0; i < cyclen; i++)
if (cyc[i].id == com[id].id)
break;
*msglen = cyc[i].buflen;
memcpy(msg, cyc[i].buf, *msglen);
}
int
eb_cmd_search_com_cyc(const unsigned char *hex, int hexlen)
{
unsigned char hlp[(CMD_SIZE_S_MSG * 2) + 1];
int i;
if (hexlen > (CMD_SIZE_S_MSG * 2)) {
log_print(L_ERR, "hexlen: %d > hlp: %d ", hexlen, (CMD_SIZE_S_MSG * 2));
return -2;
}
memset(hlp, '\0', sizeof(hlp));
for (i = 0; i < hexlen; i++)
sprintf((char *) &hlp[2 * i], "%02X", hex[i]);
for (i = 0; i < cyclen; i++) {
if (memcmp(hlp, cyc[i].msg, strlen((const char *) cyc[i].msg)) == 0) {
log_print(L_NOT, " found: %s type: %d ==> id: %d",
cyc[i].msg, com[cyc[i].id].s_type, cyc[i].id);
return cyc[i].id;
}
}
return -1;
}
int
eb_cmd_search_com_id(const char *type, const char *class, const char *cmd)
{
int i;
for (i = 0; i < comlen; i++) {
if ((strncasecmp(type, com[i].type, strlen(com[i].type)) == 0)
&& (strncasecmp(class, com[i].class, strlen(com[i].class)) == 0)
&& strlen(class) == strlen(com[i].class)
&& (strncasecmp(cmd, com[i].cmd, strlen(com[i].cmd)) == 0)
&& strlen(cmd) == strlen(com[i].cmd)) {
log_print(L_NOT, " found: %s%s%02X%s type: %d ==> id: %d",
com[i].s_zz, com[i].s_cmd, com[i].s_len,
com[i].s_msg, com[i].s_type, i);
return i;
}
}
return -1;
}
int
eb_cmd_search_com(char *buf, char *data)
{
char *type, *class, *cmd, *tok;
int id;
type = strtok(buf, " ");
class = strtok(NULL, " .");
cmd = strtok(NULL, " .\n\r\t");
if (class != NULL && cmd != NULL) {
if (strncasecmp(type, "get", 3) == 0 ||
strncasecmp(type, "set", 3) == 0 ||
strncasecmp(type, "cyc", 3) == 0) {
log_print(L_NOT, "search: %s %s.%s", type, class, cmd);
id = eb_cmd_search_com_id(type, class, cmd);
if (id < 0)
return -1;
tok = strtok(NULL, "\n\r");
if (tok == NULL)
strncpy(data, "-", 1);
else
strncpy(data, tok, strlen(tok));
log_print(L_NOT, " data: %s", data);
return id;
}
}
return -1;
}
int
eb_cmd_decode_value(int id, int elem, unsigned char *msg, char *buf)
{
char *c1, *c2, *c3, *c4;
char d_pos[CMD_SIZE_D_POS + 1];
int ret, i, j, p1, p2, p3, p4;
float f;
unsigned long l;
memset(d_pos, '\0', sizeof(d_pos));
strncpy(d_pos, com[id].elem[elem].d_pos, strlen(com[id].elem[elem].d_pos));
c1 = strtok(d_pos, " ,\n");
c2 = strtok(NULL, " ,\n");
c3 = strtok(NULL, " ,\n");
c4 = strtok(NULL, " ,\n");
p1 = c1 ? atoi(c1) : 0;
p2 = c2 ? atoi(c2) : 0;
p3 = c3 ? atoi(c3) : 0;
p4 = c4 ? atoi(c4) : 0;
log_print(L_DBG, "id: %d elem: %d p1: %d p2: %d p3: %d p4: %d", id, elem, p1, p2, p3, p4);
if (strncasecmp(com[id].elem[elem].d_type, "asc", 3) == 0) {
sprintf(buf, "%s", &msg[1]);
} else if (strncasecmp(com[id].elem[elem].d_type, "bcd", 3) == 0) {
if (p1 > 0) {
ret = eb_bcd_to_int(msg[p1], &i);
i *= com[id].elem[elem].d_fac;
sprintf(buf, "%d", i);
} else {
goto on_error;
}
} else if (strncasecmp(com[id].elem[elem].d_type, "d1b", 3) == 0) {
if (p1 > 0) {
ret = eb_d1b_to_int(msg[p1], &i);
f = i * com[id].elem[elem].d_fac;
sprintf(buf, "%f", f);
} else {
goto on_error;
}
} else if (strncasecmp(com[id].elem[elem].d_type, "d1c", 3) == 0) {
if (p1 > 0) {
ret = eb_d1c_to_float(msg[p1], &f);
f *= com[id].elem[elem].d_fac;
sprintf(buf, "%f", f);
} else {
goto on_error;
}
} else if (strncasecmp(com[id].elem[elem].d_type, "d2b", 3) == 0) {
if (p1 > 0 && p2 > 0) {
if (p1 > p2)
ret = eb_d2b_to_float(msg[p2], msg[p1], &f);
else
ret = eb_d2b_to_float(msg[p1], msg[p2], &f);
f *= com[id].elem[elem].d_fac;
sprintf(buf, "%f", f);
} else {
goto on_error;
}
} else if (strncasecmp(com[id].elem[elem].d_type, "d2c", 3) == 0) {
if (p1 > 0 && p2 > 0) {
if (p1 > p2)
ret = eb_d2c_to_float(msg[p2], msg[p1], &f);
else
ret = eb_d2c_to_float(msg[p1], msg[p2], &f);
f *= com[id].elem[elem].d_fac;
sprintf(buf, "%f", f);
} else {
goto on_error;
}
} else if (strncasecmp(com[id].elem[elem].d_type, "bda", 3) == 0) {
if (p1 > 0 && p2 > 0 && p3 > 0) {
int dd, mm, yy;
ret = eb_bcd_to_int(msg[p1], &dd);
ret = eb_bcd_to_int(msg[p2], &mm);
ret = eb_bcd_to_int(msg[p3], &yy);
ret = eb_dat_to_str(dd, mm, yy, buf);
if (ret < 0)
sprintf(buf, "error %s ==> %02x %02x %02x",
com[id].elem[elem].d_sub, msg[p1], msg[p2], msg[p3]);
} else {
goto on_error;
}
} else if (strncasecmp(com[id].elem[elem].d_type, "hda", 3) == 0) {
if (p1 > 0 && p2 > 0 && p3 > 0) {
ret = eb_dat_to_str(msg[p1], msg[p2], msg[p3], buf);
if (ret < 0)
sprintf(buf, "error %s ==> %02x %02x %02x",
com[id].elem[elem].d_sub, msg[p1], msg[p2], msg[p3]);
} else {
goto on_error;
}
} else if (strncasecmp(com[id].elem[elem].d_type, "bti", 3) == 0) {
if (p1 > 0 && p2 > 0 && p3 > 0) {
int hh, mm, ss;
ret = eb_bcd_to_int(msg[p1], &hh);
ret = eb_bcd_to_int(msg[p2], &mm);
ret = eb_bcd_to_int(msg[p3], &ss);
ret = eb_tim_to_str(hh, mm, ss, buf);
if (ret < 0)
sprintf(buf, "error %s ==> %02x %02x %02x",
com[id].elem[elem].d_sub, msg[p1], msg[p2], msg[p3]);
} else {
goto on_error;
}
} else if (strncasecmp(com[id].elem[elem].d_type, "hti", 3) == 0) {
if (p1 > 0 && p2 > 0 && p3 > 0) {
ret = eb_tim_to_str(msg[p1], msg[p2], msg[p3], buf);
if (ret < 0)
sprintf(buf, "error %s ==> %02x %02x %02x",
com[id].elem[elem].d_sub, msg[p1], msg[p2], msg[p3]);
} else {
goto on_error;
}
} else if (strncasecmp(com[id].elem[elem].d_type, "bdy", 3) == 0) {
if (p1 > 0)
ret = eb_day_to_str(msg[p1], buf);
else
goto on_error;
} else if (strncasecmp(com[id].elem[elem].d_type, "hdy", 3) == 0) {
if (p1 > 0) {
msg[p1] = msg[p1] - 0x01;
ret = eb_day_to_str(msg[p1], buf);
} else {
goto on_error;
}
} else if (strncasecmp(com[id].elem[elem].d_type, "hex", 3) == 0) {
if (p1 > 0) {
if (p2 > msg[0])
p2 = msg[0];
if (p2 == 0 || p2 < p1)
p2 = p1;
for (i = 0, j = p1 - 1; i <= p2 - p1; i++, j++)
sprintf(&buf[3 * i], "%02x ", msg[j + 1]);
buf[i * 3 - 1] = '\0';
} else {
goto on_error;
}
} else if (strncasecmp(com[id].elem[elem].d_type, "ulg", 3) == 0) {
if (p1 > 0 && p2 > 0 && p3 > 0 && p4 > 0) {
l = msg[p1] + (msg[p2] << 8) + (msg[p3] << 16) + (msg[p4] << 24);
sprintf(buf, "%lu", l);
} else {
goto on_error;
}
}
log_print(L_DBG, "buf: %s", buf);
return 0;
on_error:
strcpy(buf, "error decode");
return -1;
}
int
eb_cmd_decode(int id, char *part, char *data, unsigned char *msg, char *buf)
{
char *tok;
char tmp[CMD_DATA_SIZE], hlp[CMD_DATA_SIZE];
int ret, i, found;
/* walk through all elements */
for (i = 0; i < com[id].d_elem; i++) {
memset(tmp, '\0', sizeof(tmp));
strncpy(tmp, data, strlen(data));
/* "-" indicate no sub command, so we print all */
tok = strtok(tmp, " \n\r\t");
if (tok == NULL || strncasecmp(tok, "-", 1) == 0)
found = YES;
else
found = NO;
/* search sub command */
while (tok != NULL && found == NO) {
if (strncasecmp(com[id].elem[i].d_sub, tok,
strlen(com[id].elem[i].d_sub)) == 0 &&
strncasecmp(com[id].elem[i].d_part, part, 2) == 0) {
found = YES;
break;
}
tok = strtok(NULL, " \n\r\t");
}
if (strncasecmp(com[id].elem[i].d_part, part, 2) == 0 &&
found == YES) {
memset(hlp, '\0', sizeof(hlp));
ret = eb_cmd_decode_value(id, i, msg, hlp);
if (ret < 0) {
strncat(buf, "\n", 1);
return -1;
}
if (i > 0)
strncat(buf, " ", 1);
strncat(buf, hlp, strlen(hlp));
}
}
return 0;
}
int
eb_cmd_encode_value(int id, int elem, char *data, unsigned char *msg, char *buf)
{
char *c1, *c2, *c3;
char d_pos[CMD_SIZE_D_POS + 1];
unsigned char bcd, d1b, d1c, d2b[2], d2c[2];
int ret, i, j, p1, p2, p3;
float f;
memset(d_pos, '\0', sizeof(d_pos));
strncpy(d_pos, com[id].elem[elem].d_pos, strlen(com[id].elem[elem].d_pos));
c1 = strtok(d_pos, " ,\n");
c2 = strtok(NULL, " ,\n");
c3 = strtok(NULL, " ,\n");
p1 = c1 ? atoi(c1) : 0;
p2 = c2 ? atoi(c2) : 0;
p3 = c3 ? atoi(c3) : 0;
log_print(L_DBG, "id: %d elem: %d p1: %d p2: %d p3: %d data: %s",
id, elem, p1, p2, p3, data);
if (strncasecmp(com[id].elem[elem].d_type, "asc", 3) == 0) {
for (i = 0; i < strlen(data); i++)
sprintf((char *) &msg[i * 2], "%02x", data[i]);
} else if (strncasecmp(com[id].elem[elem].d_type, "bcd", 3) == 0) {
if (p1 > 0) {
i = (int) (atof(data) / com[id].elem[elem].d_fac);
ret = eb_int_to_bcd(i, &bcd);
sprintf((char *) msg, "%02x", bcd);
} else {
goto on_error;
}
} else if (strncasecmp(com[id].elem[elem].d_type, "d1b", 3) == 0) {
if (p1 > 0) {
i = (int) (atof(data) / com[id].elem[elem].d_fac);
ret = eb_int_to_d1b(i, &d1b);
sprintf((char *) msg, "%02x", d1b);
} else {
goto on_error;
}
} else if (strncasecmp(com[id].elem[elem].d_type, "d1c", 3) == 0) {
if (p1 > 0) {
f = (atof(data) / com[id].elem[elem].d_fac);
ret = eb_float_to_d1c(f, &d1c);
sprintf((char *) msg, "%02x", d1c);
} else {
goto on_error;
}
} else if (strncasecmp(com[id].elem[elem].d_type, "d2b", 3) == 0) {
if (p1 > 0 && p2 > 0) {
f = (atof(data) / com[id].elem[elem].d_fac);
if (p1 > p2)
ret = eb_float_to_d2b(f, &d2b[1], &d2b[0]);
else
ret = eb_float_to_d2b(f, &d2b[0], &d2b[1]);
sprintf((char *) msg, "%02x%02x", d2b[0], d2b[1]);
} else {
goto on_error;
}
} else if (strncasecmp(com[id].elem[elem].d_type, "d2c", 3) == 0) {
if (p1 > 0 && p2 > 0) {
f = (atof(data) / com[id].elem[elem].d_fac);
if (p1 > p2)
ret = eb_float_to_d2c(f, &d2c[1], &d2c[0]);
else
ret = eb_float_to_d2c(f, &d2c[0], &d2c[1]);
sprintf((char *) msg, "%02x%02x", d2c[0], d2c[1]);
} else {
goto on_error;
}
} else if (strncasecmp(com[id].elem[elem].d_type, "hda", 3) == 0) {
if (p1 > 0 && p2 > 0 && p3 > 0) {
int dd, mm, yy;
dd = atoi(strtok(data, " .\n"));
mm = atoi(strtok(NULL, " .\n"));
yy = atoi(strtok(NULL, " .\n"));
ret = eb_str_to_dat(dd, mm, yy, msg);
if (ret < 0)
sprintf(buf, "error ==> %d.%d.%d", dd, mm, yy);
} else {
goto on_error;
}
} else if (strncasecmp(com[id].elem[elem].d_type, "hti", 3) == 0) {
if (p1 > 0 && p2 > 0 && p3 > 0) {
int hh, mm, ss;
hh = atoi(strtok(data, " :\n"));
mm = atoi(strtok(NULL, " :\n"));
ss = atoi(strtok(NULL, " :\n"));
ret = eb_str_to_tim(hh, mm, ss, msg);
if (ret < 0)
sprintf(buf, "error ==> %d:%d:%d", hh, mm, ss);
} else {
goto on_error;
}
} else if (strncasecmp(com[id].elem[elem].d_type, "hdy", 3) == 0) {
if (p1 > 0) {
int day;
day = atoi(data);
sprintf((char *) msg, "%02x", day);
} else {
goto on_error;
}
} else if (strncasecmp(com[id].elem[elem].d_type, "hex", 3) == 0) {
for (i = 0, j = 0; data[i]; i++) {
if (isxdigit(data[i])) {
msg[j] = tolower(data[i]);
j++;
} else if (data[i] != ' ') {
goto on_error;
}
}
}
return 0;
on_error:
strcpy(buf, "error encode");
return -1;
}
int
eb_cmd_encode(int id, char *data, unsigned char *msg, char *buf)
{
char *tok, *toksave;
unsigned char hlp[CMD_SIZE_S_MSG + 1];
int ret, i;
tok = strtok_r(data, " \n\r\t", &toksave);
/* walk through all elements */
for (i = 0; i < com[id].d_elem; i++) {
if (tok != NULL) {
memset(hlp, '\0', sizeof(hlp));
ret = eb_cmd_encode_value(id, i, tok, hlp, buf);
if (ret < 0) {
strncat(buf, "\n", 1);
return -1;
}
strncat((char *) msg, (const char *) hlp, strlen((const char *) hlp));
} else {
return -1;
}
tok = strtok_r(NULL, " \n\r\t", &toksave);
}
if (strlen(buf) > 0)
strncat(buf, "\n", 1);
return 0;
}
void
eb_cmd_prepare(int id, char *data, unsigned char *msg, int *msglen, char *buf)
{
unsigned char tmp[CMD_SIZE_S_MSG + 1];
char str[CMD_SIZE_S_ZZ + CMD_SIZE_S_CMD + 2 + CMD_SIZE_S_MSG + 1];
char byte;
int ret, i, j, k;
int in[SERIAL_BUFSIZE];
/* encode msg */
memset(tmp, '\0', sizeof(tmp));
if (strncasecmp(com[id].type, "set", 3) == 0)
eb_cmd_encode(id, data, tmp, buf);
memset(str, '\0', sizeof(str));
sprintf(str, "%s%s%02X%s%s",
com[id].s_zz, com[id].s_cmd, com[id].s_len, com[id].s_msg, tmp);
memset(in, '\0', sizeof(in));
i = 0;
j = 0;
while (str[j] != '\0') {
byte = str[j];
if (i < sizeof(in)) {
ret = eb_htoi(&byte);
if (ret != -1) {
in[i] = ret;
i++;
}
}
j++;
}
memset(msg, '\0', sizeof(msg));
for (j = 0, k = 0; j < i; j += 2, k++)
msg[k] = (unsigned char) (in[j]*16 + in[j+1]);
*msglen = k;
}
void
eb_cmd_print(const char *type, int all, int detail)
{
int i, j;
for (i = 0; i < comlen; i++) {
if (strncasecmp(com[i].type, type, 1) == 0 || all) {
log_print(L_INF, "[%03d] %s : %5s.%-32s\t(type: %d)" \
" %s%s%-10s (len: %d) [%d] ==> %s",
com[i].id,
com[i].type,
com[i].class,
com[i].cmd,
com[i].s_type,
com[i].s_zz,
com[i].s_cmd,
com[i].s_msg,
com[i].s_len,
com[i].d_elem,
com[i].com
);
if (detail) {
for (j = 0; j < com[i].d_elem; j++) {
log_print(L_INF, "\t\t %-20s %-2s " \
"pos: %-10s\t%s [%5.2f] [%s] \t%s\t%s",
com[i].elem[j].d_sub,
com[i].elem[j].d_part,
com[i].elem[j].d_pos,
com[i].elem[j].d_type,
com[i].elem[j].d_fac,
com[i].elem[j].d_unit,
com[i].elem[j].d_valid,
com[i].elem[j].d_com
);
}
log_print(L_INF, "");
}
}
}
}
int
eb_cmd_fill(const char *tok)
{
int i;
com = (struct commands *) realloc(com, (comlen + 1) * sizeof(struct commands));
err_ret_if(com == NULL, -1);
memset(com + comlen, '\0', sizeof(struct commands));
/* id */
com[comlen].id = comlen;
/* type */
strncpy(com[comlen].type, tok, strlen(tok));
/* class */
tok = strtok(NULL, ";");
strncpy(com[comlen].class, tok, strlen(tok));
/* cmd */
tok = strtok(NULL, ";");
strncpy(com[comlen].cmd, tok, strlen(tok));
/* com */
tok = strtok(NULL, ";");
strncpy(com[comlen].com, tok, strlen(tok));
/* s_type */
tok = strtok(NULL, ";");
com[comlen].s_type = atoi(tok);
/* s_zz */
tok = strtok(NULL, ";");
strncpy(com[comlen].s_zz, tok, strlen(tok));
eb_cmd_uppercase(com[comlen].s_zz);
/* s_cmd */
tok = strtok(NULL, ";");
strncpy(com[comlen].s_cmd, tok, strlen(tok));
eb_cmd_uppercase(com[comlen].s_cmd);
/* s_len */
tok = strtok(NULL, ";");
com[comlen].s_len = atoi(tok);
/* s_msg */
tok = strtok(NULL, ";");
if (strncasecmp(tok, "-", 1) != 0) {
strncpy(com[comlen].s_msg, tok, strlen(tok));
eb_cmd_uppercase(com[comlen].s_msg);
}
/* d_elem */
tok = strtok(NULL, ";");
com[comlen].d_elem = atoi(tok);
com[comlen].elem = (struct element *) malloc(com[comlen].d_elem * sizeof(struct element));
err_ret_if(com[comlen].elem == NULL, -1);
memset(com[comlen].elem, '\0', com[comlen].d_elem * sizeof(struct element));
for (i = 0; i < com[comlen].d_elem; i++) {
/* d_sub */
tok = strtok(NULL, ";");
if (strncasecmp(tok, "-", 1) != 0)
strncpy(com[comlen].elem[i].d_sub, tok, strlen(tok));
/* d_part */
tok = strtok(NULL, ";");
strncpy(com[comlen].elem[i].d_part, tok, strlen(tok));
/* d_pos */
tok = strtok(NULL, ";");
strncpy(com[comlen].elem[i].d_pos, tok, strlen(tok));
/* d_type */
tok = strtok(NULL, ";");
strncpy(com[comlen].elem[i].d_type, tok, strlen(tok));
/* d_fac */
tok = strtok(NULL, ";");
com[comlen].elem[i].d_fac = atof(tok);
/* d_unit */
tok = strtok(NULL, ";");
strncpy(com[comlen].elem[i].d_unit, tok, strlen(tok));
/* d_valid */
tok = strtok(NULL, ";");
strncpy(com[comlen].elem[i].d_valid, tok, strlen(tok));
/* d_com */
tok = strtok(NULL, ";");
strncpy(com[comlen].elem[i].d_com, tok, strlen(tok));
com[comlen].elem[i].d_com[strcspn(com[comlen].elem[i].d_com, "\n")] = '\0';
}
if (strncasecmp(com[comlen].type, "cyc", 3) == 0) {
cyc = (struct cycbuf *) realloc(cyc, (cyclen + 1) * sizeof(struct cycbuf));
err_ret_if(cyc == NULL, -1);
memset(cyc + cyclen, '\0', sizeof(struct cycbuf));
/* id */
cyc[cyclen].id = com[comlen].id;
/* msg */
sprintf((char *) cyc[cyclen].msg, "%s%s%02X%s",
com[comlen].s_zz, com[comlen].s_cmd,
com[comlen].s_len, com[comlen].s_msg);
cyclen++;
}
comlen++;
return 0;
}
int
eb_cmd_num_c(const char *str, const char c)
{
const char *p = str;
int i = 0;
do {
if (*p == c)
i++;
} while (*(p++));
return i;
}
int
eb_cmd_file_read(const char *file)
{
int ret;
char line[CMD_LINELEN];
char *tok;
FILE *fp = NULL;
log_print(L_NOT, "%s", file);
/* open config file */
fp = fopen(file, "r");
err_ret_if(fp == NULL, -1);
/* read each line and fill cmd array */
while (fgets(line, CMD_LINELEN, fp) != NULL) {
tok = strtok(line, ";\n");
if (tok != NULL && tok[0] != '#' ) {
ret = eb_cmd_fill(tok);
if (ret < 0)
return -2;
}
}
/* close config file */
ret = fclose(fp);
err_ret_if(ret == EOF, -1);
log_print(L_NOT, "%s success", file);
return 0;
}
int
eb_cmd_dir_read(const char *cfgdir, const char *extension)
{
struct dirent **dir;
int ret, i, j, files, extlen;
char file[CMD_FILELEN], extprep[11];
char *ext;
extlen = strlen(extension) + 1;
memset(extprep, '\0', sizeof(extprep));
extprep[0] = '.';
strncpy(&extprep[1], extension, strlen(extension));
files = scandir(cfgdir, &dir, 0, alphasort);
if (files < 0) {
log_print(L_WAR, "configuration directory %s not found.", cfgdir);
return 1;
}
i = 0;
j = 0;
while (i < files) {
ext = strrchr(dir[i]->d_name, '.');
if (ext != NULL) {
if (strlen(ext) == extlen
&& dir[i]->d_type == DT_REG
&& strncasecmp(ext, extprep, extlen) == 0 ) {
memset(file, '\0', sizeof(file));
sprintf(file, "%s/%s", cfgdir, dir[i]->d_name);
ret = eb_cmd_file_read(file);
if (ret < 0)
return -1;
j++;
}
}
free(dir[i]);
i++;
}
free(dir);
if (j == 0) {
log_print(L_WAR, "no command files found ==> decode disabled.");
return 2;
}
return 0;
}
void
eb_cmd_dir_free(void)
{
int i;
if (comlen > 0) {
for (i = 0; i < comlen; i++)
free(&com[i].elem[0]);
free(com);
}
if (cyclen > 0)
free(cyc);
}
+290
View File
@@ -0,0 +1,290 @@
/*
* Copyright (C) Roland Jax 2012-2013 <roland.jax@liwest.at>
*
* This file is part of ebusd.
*
* ebusd 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.
*
* ebusd 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 ebusd. If not, see http://www.gnu.org/licenses/.
*/
/**
* @file ebus-cmd.h
* @brief ebus command file functions
* @author roland.jax@liwest.at
* @version 0.1
*/
#ifndef EBUS_CMD_H_
#define EBUS_CMD_H_
#include <sys/time.h>
#include "ebus-common.h"
#define CMD_LINELEN 512
#define CMD_FILELEN 1024
#define CMD_SIZE_TYPE 3
#define CMD_SIZE_CLASS 20
#define CMD_SIZE_CMD 30
#define CMD_SIZE_COM 256
#define CMD_SIZE_S_ZZ 2
#define CMD_SIZE_S_CMD 4
#define CMD_SIZE_S_MSG 32
#define CMD_SIZE_D_SUB 20
#define CMD_SIZE_D_PART 2
#define CMD_SIZE_D_POS 10
#define CMD_SIZE_D_TYPE 3
#define CMD_SIZE_D_UNIT 6
#define CMD_SIZE_D_VALID 30
#define CMD_SIZE_D_COM 256
#define CMD_PART_MD "MD"
#define CMD_PART_SA "SA"
#define CMD_PART_SD "SD"
#define CMD_PART_MA "MA"
/**
* @brief cycbuf structure
*/
struct cycbuf {
int id; /**< command id from command buffer */
unsigned char msg[CMD_SIZE_S_MSG + 1]; /**< zz + cmd + len + msg */
unsigned char buf[CMD_DATA_SIZE + 1]; /**< whole message - unescaped */
int buflen; /**< len of saved message */
};
/**
* @brief commands structure
*/
struct commands {
int id; /**< command id */
char type[CMD_SIZE_TYPE + 1]; /**< type of message */
char class[CMD_SIZE_CLASS + 1]; /**< ci */
char cmd[CMD_SIZE_CMD + 1]; /**< hydraulic */
char com[CMD_SIZE_COM + 1]; /**< just a comment */
int s_type; /**< message type */
char s_zz[CMD_SIZE_S_ZZ + 1]; /**< zz */
char s_cmd[CMD_SIZE_S_CMD + 1]; /**< pb sb */
int s_len; /**< number of send bytes */
char s_msg[CMD_SIZE_S_MSG + 1]; /**< max 15 data bytes */
int d_elem; /**< number of elements */
struct element *elem; /**< pointer of array with elements */
};
/**
* @brief element structure
*/
struct element {
char d_sub[CMD_SIZE_D_SUB + 1]; /**< pin1 */
char d_part[CMD_SIZE_D_PART + 1]; /**< part of message */
char d_pos[CMD_SIZE_D_POS + 1]; /**< data position at bytes */
char d_type[CMD_SIZE_D_TYPE + 1]; /**< data type */
float d_fac; /**< facter */
char d_unit[CMD_SIZE_D_UNIT + 1]; /**< unit of data like °C,...) */
char d_valid[CMD_SIZE_D_VALID + 1]; /**< valid data */
char d_com[CMD_SIZE_D_COM + 1]; /**< just a comment */
};
/**
* @brief convert string to uppercase
* @param [out] *buf pointer to buffer array
*/
void eb_cmd_uppercase(char *buf);
/**
* @brief compare given type with type of given command id
* @param [in] id is index in command array
* @param [in] type for lookup
* @return YES or NO
*/
int eb_cmd_check_type(int id, const char *type);
/**
* @brief returns s_type of given id
* @param [in] id is index in command array
* @return s_type of ebus command
*/
int eb_cmd_get_s_type(int id);
/**
* @brief set buf from cyc array
* @param [in] id is index in command array
* @param [in] *msg pointer to message array
* @param [in] msglen pointer to message length
* @return none
*/
void eb_cmd_set_cyc_buf(int id, const unsigned char *msg, int msglen);
/**
* @brief get buf from cyc array
* @param [in] id is index in command array
* @param [out] *msg pointer to message array
* @param [out] *msglen pointer to message length
* @return none
*/
void eb_cmd_get_cyc_buf(int id, unsigned char *msg, int *msglen);
/**
* @brief search given strings in cycbuf array
* @param [in] *hex pointer to hex string
* @return 0-x id of found ebus command in array
* -1 command not found | -2 hexlen too long
*/
int eb_cmd_search_com_cyc(const unsigned char *hex, int hexlen);
/**
* @brief search given strings in command array
* @param [in] *type pointer to message type
* @param [in] *class pointer to a ebus class
* @param [in] *cmd pointer to a ebus command
* @return 0-x id of found ebus command in array | -1 command not found
*/
int eb_cmd_search_com_id(const char *type, const char *class, const char *cmd);
/**
* @brief search given strings in command array
* @param [in] *buf pointer to a byte array
* @param [out] *data pointer to data array for passing to decode/encode
* @return 0-x id of found ebus command in array | -1 command not found
*/
int eb_cmd_search_com(char *buf, char *data);
/**
* @brief decode given element
* @param [in] id is index in command array
* @param [in] elem is index of data position
* @param [out] *msg pointer to message array
* @param [out] *buf pointer to decoded answer
* @return 0 ok | -1 error at decode
*/
int eb_cmd_decode_value(int id, int elem, unsigned char *msg, char *buf);
/**
* @brief decode msg
* @param [in] id is index in command array
* @param [in] *part point to part type for decode
* @param [in] *data pointer to data bytes for decode
* @param [out] *msg pointer to message array
* @param [out] *buf pointer to decoded answer
* @return 0 ok | -1 error at decode
*/
int eb_cmd_decode(int id, char *part, char *data, unsigned char *msg, char *buf);
/**
* @brief decode given element
* @param [in] id is index in command array
* @param [in] elem is index of data position
* @param [in] *data pointer to data bytes for encode
* @param [out] *msg pointer to message array
* @param [out] *buf pointer to decoded answer
* @return 0 ok | -1 error at decode
*/
int eb_cmd_encode_value(int id, int elem, char *data, unsigned char *msg, char *buf);
/**
* @brief encode msg
* @param [in] id is index in command array
* @param [in] *data pointer to data bytes for encode
* @param [out] *msg pointer to message array
* @param [out] *buf pointer to decoded answer
* @return 0 ok | -1 error at encode
*/
int eb_cmd_encode(int id, char *data, unsigned char *msg, char *buf);
/**
* @brief prepare message string for given ebus cmd from array
* @param [in] id is index in command array
* @param [in] *data pointer to data bytes for decode/encode
* @param [out] *msg pointer to message array
* @param [out] *msglen pointer to message length
* @param [out] *buf pointer to decoded answer
* @return none
*/
void eb_cmd_prepare(int id, char *data, unsigned char *msg, int *msglen, char *buf);
/**
* @brief print readed ebus commands
* @param [in] *type (get/set/cyc)
* @param [in] all print all
* @param [in] detail show details of command
* @return none
*/
void eb_cmd_print(const char *type, int all, int detail);
/**
* @brief fill command structure
* @param [in] *tok pointer to given token
* @return 0 ok | -1 error
*/
int eb_cmd_fill(const char *tok);
/**
* @brief prevent buffer overflow
*
* number of tokens must be >= number of columns - 1 of file
*
* @param [in] *buf pointer to a byte array
* @param [in] delimeter
* @return number of found delimeters
*/
int eb_cmd_num_c(const char *buf, const char c);
/**
* @brief set cfgdir address
* @param [in] *file pointer to configuration file with *.csv
* @return 0 ok | -1 error | -2 read token error
*/
int eb_cmd_file_read(const char *file);
/**
* @brief get all files with given extension from given configuration directory
* @param [in] *cfgdir pointer to configuration directory
* @param [in] *suffix pointer to given extension
* @return 0 ok | -1 error | 1 read file error | 2 no command files found
*/
int eb_cmd_dir_read(const char *cfgdir, const char *extension);
/**
* @brief free mem for ebus commands
* @return none
*/
void eb_cmd_dir_free(void);
#endif /* EBUS_CMD_H_ */
+65
View File
@@ -0,0 +1,65 @@
/*
* Copyright (C) Roland Jax 2012-2013 <roland.jax@liwest.at>
* crc calculations from http://www.mikrocontroller.net/topic/75698
*
* This file is part of ebusd.
*
* ebusd 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.
*
* ebusd 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 ebusd. If not, see http://www.gnu.org/licenses/.
*/
/**
* @file ebus-common.h
* @brief ebus common defines
* @author roland.jax@liwest.at
* @version 0.1
*/
#ifndef EBUS_COMMON_H_
#define EBUS_COMMON_H_
#define EBUS_SYN 0xAA
#define EBUS_SYN_ESC_A9 0xA9
#define EBUS_SYN_ESC_01 0x01
#define EBUS_SYN_ESC_00 0x00
#define EBUS_ACK 0x00
#define EBUS_NAK 0xFF
#define EBUS_QQ 0xFF
#define EBUS_GET_RETRY 3
#define EBUS_GET_RETRY_MAX 10
#define EBUS_SKIP_ACK 1
#define EBUS_MAX_WAIT 4000
#define EBUS_SEND_RETRY 2
#define EBUS_SEND_RETRY_MAX 10
#define EBUS_PRINT_SIZE 30
#define EBUS_MSG_BROADCAST 1
#define EBUS_MSG_MASTER_MASTER 2
#define EBUS_MSG_MASTER_SLAVE 3
#define SERIAL_DEVICE "/dev/ttyUSB0"
#define SERIAL_BAUDRATE B2400
#define SERIAL_BUFSIZE 100
#define CMD_DATA_SIZE 50 /* 5+16+3+16+2 = 42 || 256 */
enum enum_bool {UNSET = -1, NO, YES};
#endif /* EBUS_COMMON_H_ */
+439
View File
@@ -0,0 +1,439 @@
/*
* Copyright (C) Roland Jax 2012-2013 <roland.jax@liwest.at>
* crc calculations from http://www.mikrocontroller.net/topic/75698
*
* This file is part of ebusd.
*
* ebusd 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.
*
* ebusd 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 ebusd. If not, see http://www.gnu.org/licenses/.
*/
/**
* @file ebus-decode.c
* @brief ebus decode functions
* @author roland.jax@liwest.at
* @version 0.1
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "ebus-decode.h"
const char *days[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
int
eb_htoi(const char *buf)
{
int ret;
ret = -1;
if (isxdigit(*buf)) {
if (isalpha(*buf))
ret = 55;
else
ret = 48;
ret = toupper(*buf) - ret;
}
return ret;
}
void
eb_esc(unsigned char *buf, int *buflen)
{
unsigned char tmp[SERIAL_BUFSIZE];
int tmplen, i;
memset(tmp, '\0', sizeof(tmp));
i = 0;
tmplen = 0;
while (i < *buflen) {
if (buf[i] == EBUS_SYN) {
tmp[tmplen] = EBUS_SYN_ESC_A9;
tmplen++;
tmp[tmplen] = EBUS_SYN_ESC_01;
tmplen++;
} else if (buf[i] == EBUS_SYN_ESC_A9) {
tmp[tmplen] = EBUS_SYN_ESC_A9;
tmplen++;
tmp[tmplen] = EBUS_SYN_ESC_00;
tmplen++;
} else {
tmp[tmplen] = buf[i];
tmplen++;
}
i++;
}
memset(buf, '\0', sizeof(buf));
for (i = 0; i < tmplen; i++)
buf[i] = tmp[i];
*buflen = tmplen;
}
void
eb_unesc(unsigned char *buf, int *buflen)
{
unsigned char tmp[SERIAL_BUFSIZE];
int tmplen, i, found;
memset(tmp, '\0', sizeof(tmp));
i = 0;
tmplen = 0;
found = 0;
while (i < *buflen) {
if (buf[i] == EBUS_SYN_ESC_A9) {
found = 1;
} else if (found == 1) {
if (buf[i] == EBUS_SYN_ESC_01) {
tmp[tmplen] = EBUS_SYN;
tmplen++;
} else {
tmp[tmplen] = EBUS_SYN_ESC_A9;
tmplen++;
}
found = 0;
} else {
tmp[tmplen] = buf[i];
tmplen++;
}
i++;
}
memset(buf, '\0', sizeof(buf));
for (i = 0; i < tmplen; i++)
buf[i] = tmp[i];
*buflen = tmplen;
}
int
eb_day_to_str(unsigned char day, char *tgt)
{
int dd;
if (dd >= 0x00 && dd <= 0x06) {
eb_bcd_to_int(day, &dd);
sprintf(tgt, "%s", days[day]);
} else {
return -1;
}
return 0;
}
int
eb_dat_to_str(unsigned char dd, unsigned char mm, unsigned char yy, char *tgt)
{
if (dd >= 0x00 && dd <= 0x1F &&
mm >= 0x00 && mm <= 0x0C &&
yy >= 0x00 && yy <= 0x63 )
sprintf(tgt, "%02d.%02d.%04d", dd, mm, yy + 2000);
else
return -1;
return 0;
}
int
eb_str_to_dat(int dd, int mm, int yy, unsigned char *tgt)
{
if (yy > 2000)
yy -= 2000;
if (dd >= 0 && dd <= 31 &&
mm >= 0 && mm <= 12 &&
yy >= 0 && yy <= 99 )
sprintf((char *) tgt, "%02x%02x%02x", dd, mm, yy);
else
return -1;
return 0;
}
int
eb_tim_to_str(unsigned char hh, unsigned char mm, unsigned char ss, char *tgt)
{
if (hh >= 0x00 && hh <= 0x17 &&
mm >= 0x00 && mm <= 0x3B &&
ss >= 0x00 && ss <= 0x3B )
sprintf(tgt, "%02d:%02d:%02d", hh, mm, ss);
else
return -1;
return 0;
}
int
eb_str_to_tim(int hh, int mm, int ss, unsigned char *tgt)
{
if (hh >= 0 && hh <= 23 &&
mm >= 0 && mm <= 59 &&
ss >= 0 && ss <= 59 )
sprintf((char *) tgt, "%02x%02x%02x", hh, mm, ss);
else
return -1;
return 0;
}
int
eb_bcd_to_int(unsigned char src, int *tgt)
{
if ((src & 0x0F) > 0x09 || ((src >> 4) & 0x0F) > 0x09) {
*tgt = (int) (0xFF);
return 0;
} else {
*tgt = (int) ( ( ((src & 0xF0) >> 4) * 10) + (src & 0x0F) );
return 1;
}
}
int
eb_int_to_bcd(int src, unsigned char *tgt)
{
if (src > 99) {
*tgt = (unsigned char) (0xFF);
return 0;
} else {
*tgt = (unsigned char) ( ((src / 10) << 4) | (src % 10) );
return 1;
}
}
int
eb_d1b_to_int(unsigned char src, int *tgt)
{
if ((src & 0x80) == 0x80) {
*tgt = (int) (- ( ((unsigned char) (~ src)) + 1) );
if (*tgt == -0x80)
return 0;
else
return -1;
} else {
*tgt = (int) (src);
return 1;
}
}
int
eb_int_to_d1b(int src, unsigned char *tgt)
{
if (src < -127 || src > 127) {
*tgt = (unsigned char) (0x80);
return 0;
} else {
if (src >= 0) {
*tgt = (unsigned char) (src);
return 1;
} else {
*tgt = (unsigned char) (- (~ (src - 1) ) );
return -1;
}
}
}
int
eb_d1c_to_float(unsigned char src, float *tgt)
{
if (src > 0xC8) {
*tgt = (float) (0xFF);
return 0;
} else {
*tgt = (float) (src / 2.0);
return 1;
}
}
int
eb_float_to_d1c(float src, unsigned char *tgt)
{
if (src < 0.0 || src > 100.0) {
*tgt = (unsigned char) (0xFF);
return 0;
} else {
*tgt = (unsigned char) (src * 2.0);
return 1;
}
}
int
eb_d2b_to_float(unsigned char src_lsb, unsigned char src_msb, float *tgt)
{
if ((src_msb & 0x80) == 0x80) {
*tgt = (float)
(- ( ((unsigned char) (~ src_msb)) +
( ( ((unsigned char) (~ src_lsb)) + 1) / 256.0) ) );
if (src_msb == 0x80 && src_lsb == 0x00)
return 0;
else
return -1;
} else {
*tgt = (float) (src_msb + (src_lsb / 256.0));
return 1;
}
}
int
eb_float_to_d2b(float src, unsigned char *tgt_lsb, unsigned char *tgt_msb)
{
if (src < -127.999 || src > 127.999) {
*tgt_msb = (unsigned char) (0x80);
*tgt_lsb = (unsigned char) (0x00);
return 0;
} else {
*tgt_lsb = (unsigned char) ((src - ((unsigned char) src)) * 256.0);
if (src < 0.0 && *tgt_lsb != 0x00)
*tgt_msb = (unsigned char) (src - 1);
else
*tgt_msb = (unsigned char) (src);
if (src >= 0.0)
return 1;
else
return -1;
}
}
int
eb_d2c_to_float(unsigned char src_lsb, unsigned char src_msb, float *tgt)
{
if ((src_msb & 0x80) == 0x80) {
*tgt = (float)
(- ( ( ( ((unsigned char) (~ src_msb)) * 16.0) ) +
( ( ((unsigned char) (~ src_lsb)) & 0xF0) >> 4) +
( ( ( ((unsigned char) (~ src_lsb)) & 0x0F) +1 ) / 16.0) ) );
if (src_msb == 0x80 && src_lsb == 0x00)
return 0;
else
return -1;
} else {
*tgt = (float) ( (src_msb * 16.0) + ((src_lsb & 0xF0) >> 4) +
((src_lsb & 0x0F) / 16.0) );
return 1;
}
}
int
eb_float_to_d2c(float src, unsigned char *tgt_lsb, unsigned char *tgt_msb)
{
if (src < -2047.999 || src > 2047.999) {
*tgt_msb = (unsigned char) (0x80);
*tgt_lsb = (unsigned char) (0x00);
return 0;
} else {
*tgt_lsb =
( ((unsigned char) ( ((unsigned char) src) % 16) << 4) +
((unsigned char) ( (src - ((unsigned char) src)) * 16.0)) );
if (src < 0.0 && *tgt_lsb != 0x00)
*tgt_msb = (unsigned char) ((src / 16.0) - 1);
else
*tgt_msb = (unsigned char) (src / 16.0);
if (src >= 0.0)
return 1;
else
return -1;
}
}
unsigned char
eb_calc_crc_byte(unsigned char byte, unsigned char init_crc)
{
unsigned char crc, polynom;
int i;
crc = init_crc;
for (i = 0; i < 8; i++) {
if (crc & 0x80)
polynom = (unsigned char) 0x9B;
else
polynom = (unsigned char) 0;
crc = (unsigned char) ((crc & ~0x80) << 1);
if (byte & 0x80)
crc = (unsigned char) (crc | 1);
crc = (unsigned char) (crc ^ polynom);
byte = (unsigned char) (byte << 1);
}
return crc;
}
unsigned char
eb_calc_crc(const unsigned char *buf, int buflen)
{
int i;
unsigned char crc = 0;
for (i = 0 ; i < buflen ; i++, buf++)
crc = eb_calc_crc_byte(*buf, crc);
return crc;
}
+242
View File
@@ -0,0 +1,242 @@
/*
* Copyright (C) Roland Jax 2012-2013 <roland.jax@liwest.at>
* crc calculations from http://www.mikrocontroller.net/topic/75698
*
* This file is part of ebusd.
*
* ebusd 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.
*
* ebusd 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 ebusd. If not, see http://www.gnu.org/licenses/.
*/
/**
* @file ebus-decode.h
* @brief ebus decode functions
* @author roland.jax@liwest.at
* @version 0.1
*/
/*
* name type description resolution substitue
* BCD CHAR 0 ... + 99 1 FFh
* DATA1b SIGNED CHAR - 127 ... + 127 1 80h
* DATA1c CHAR 0 ... + 100 0,5 FFh
* DATA2b SIGNED INTEGER - 127,99 ... + 127,99 1/256 8000h
* DATA2c SIGNED INTEGER -2047,9 ... + 2047,9 1/16 8000h
*/
#ifndef EBUS_DECODE_H_
#define EBUS_DECODE_H_
#include "ebus-common.h"
/**
* @brief calculate integer value of given hex byte
* @param [in] *buf hex byte
* @return integer value | -1 if given byte is no hex value
*/
int eb_htoi(const char *buf);
/**
* @brief print received results in a specific format
* @param [out] *buf pointer to a byte array
* @param [out] *buflen length of byte array
* @return none
*/
void eb_esc(unsigned char *buf, int *buflen);
/**
* @brief print received results in a specific format
* @param [out] *buf pointer to a byte array
* @param [out] *buflen length of byte array
* @return none
*/
void eb_unesc(unsigned char *buf, int *buflen);
/**
* @brief convert hex bytes to day
* @param [in] day hex byte
* @param [out] *tgt pointer to day string xxx
* @return 0 OK | -1 values out of range
*/
int eb_day_to_str(unsigned char day, char *tgt);
/**
* @brief convert hex bytes to date
* @param [in] dd day hex byte
* @param [in] mm month hex byte
* @param [in] yy year hex byte
* @param [out] *tgt pointer to date string dd.mm.yyyy
* @return 0 OK | -1 values out of range
*/
int eb_dat_to_str(unsigned char dd, unsigned char mm, unsigned char yy, char *tgt);
/**
* @brief convert char date string to hex
* @param [in] dd day int value
* @param [in] mm month int value
* @param [in] yy year int value
* @param [out] *tgt pointer to hex
* @return 0 OK | -1 values out of range
*/
int eb_str_to_dat(int dd, int mm, int yy, unsigned char *tgt);
/**
* @brief convert hex bytes to date
* @param [in] hh hour hex byte
* @param [in] mm minute hex byte
* @param [in] ss second hex byte
* @param [out] *tgt pointer to date string hh:mm:ss
* @return 0 OK | -1 values out of range
*/
int eb_tim_to_str(unsigned char hh, unsigned char mm, unsigned char ss, char *tgt);
/**
* @brief convert char time string to hex
* @param [in] hh hour int value
* @param [in] mm minute int value
* @param [in] ss second int value
* @param [out] *tgt pointer to hex
* @return 0 OK | -1 values out of range
*/
int eb_str_to_tim(int hh, int mm, int ss, unsigned char *tgt);
/**
* @brief convert bcd hex byte to int
* @param [in] src bcd hex byte
* @param [out] *tgt pointer to int value
* @return 0 substitute value | 1 positive value
*/
int eb_bcd_to_int(unsigned char src, int *tgt);
/**
* @brief convert int to bcd hex byte
* @param [in] src int value
* @param [out] *tgt pointer to hex byte
* @return 0 substitute value | 1 positive value
*/
int eb_int_to_bcd(int src, unsigned char *tgt);
/**
* @brief convert data1b hex byte to int
* @param [in] src data1b hex byte
* @param [out] *tgt pointer to int value
* @return 0 substitute value | 1 positive value | -1 negative value
*/
int eb_d1b_to_int(unsigned char src, int *tgt);
/**
* @brief convert int to data1b hex byte
* @param [in] src int value
* @param [out] *tgt pointer to data1b hex byte
* @return 0 substitute value | 1 positive value | -1 negative value
*/
int eb_int_to_d1b(int src, unsigned char *tgt);
/**
* @brief convert data1c hex byte to float
* @param [in] src data1c hex byte
* @param [out] *tgt pointer to float value
* @return 0 substitute value | 1 positive value | -1 negative value
*/
int eb_d1c_to_float(unsigned char src, float *tgt);
/**
* @brief convert float to data1c hex byte
* @param [in] src float value
* @param [out] *tgt pointer to data1c hex byte
* @return 0 substitute value | 1 positive value | -1 negative value
*/
int eb_float_to_d1c(float src, unsigned char *tgt);
/**
* @brief convert data2b hex bytes to float
* @param [in] src_lsb least significant data2b hex byte
* @param [in] src_msb most significant data2b hex byte
* @param [out] *tgt pointer to float value
* @return 0 substitute value | 1 positive value | -1 negative value
*/
int eb_d2b_to_float(unsigned char src_lsb, unsigned char src_msb, float *tgt);
/**
* @brief convert float to data2b hex bytes
* @param [in] src float value
* @param [out] *tgt_lsb pointer to least significant data2b hex byte
* @param [out] *tgt_msb pointer to most significant data2b hex byte
* @return 0 substitute value | 1 positive value | -1 negative value
*/
int eb_float_to_d2b(float src, unsigned char *tgt_lsb, unsigned char *tgt_msb);
/**
* @brief convert data2c hex bytes to float
* @param [in] src_lsb least significant data2c hex byte
* @param [in] src_msb most significant data2c hex byte
* @param [out] *tgt pointer to float value
* @return 0 substitute value | 1 positive value | -1 negative value
*/
int eb_d2c_to_float(unsigned char src_lsb, unsigned char src_msb, float *tgt);
/**
* @brief convert float to data2c hex bytes
* @param [in] src float value
* @param [out] *tgt_lsb pointer to least significant data2c hex byte
* @param [out] *tgt_msb pointer to most significant data2c hex byte
* @return 0 substitute value | 1 positive value | -1 negative value
*/
int eb_float_to_d2c(float src, unsigned char *tgt_lsb, unsigned char *tgt_msb);
/**
* @brief calculate crc of hex byte
* @param [in] byte byte to calculate
* @param [in] init_crc start value for calculation
* @return new calculated crc byte from byte and init crc byte
*/
unsigned char eb_calc_crc_byte(unsigned char byte, unsigned char init_crc);
/**
* @brief calculate crc of given hex array
*
* \li crc calculation "CRC-8-WCDMA" with Polynom "x^8+x^7+x^4+x^3+x+1"
* \li crc calculations by http://www.mikrocontroller.net/topic/75698
*
* @param [in] *bytes pointer to a byte array
* @param [in] size length of given bytes
* @return calculated crc byte
*/
unsigned char eb_calc_crc(const unsigned char *bytes, int size);
#endif /* EBUS_DECODE_H_ */
+181
View File
@@ -0,0 +1,181 @@
/*
* Copyright (C) Roland Jax 2012-2013 <roland.jax@liwest.at>
*
* This file is part of ebusd.
*
* ebusd 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.
*
* ebusd 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 ebusd. If not, see http://www.gnu.org/licenses/.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <time.h>
#include <unistd.h>
#include <sys/time.h>
#include <syslog.h>
#include "log.h"
static unsigned char loglvl = L_NUL;
static int logtxtlen = sizeof(logtxt) / sizeof(char*);
static FILE *logfp = NULL;
char *log_time(char *time);
char *log_txt(unsigned char lvl);
void
log_file(FILE *fp)
{
if(logfp)
fclose(logfp);
logfp = fp;
}
void
log_level(char *lvl)
{
unsigned char tmp;
int i;
char *par;
loglvl = L_NUL;
par = strtok(lvl, ", ");
while (par) {
if (strncasecmp(par, "ALL", 3) == 0) {
loglvl = L_ALL;
break;
}
tmp = 0x01;
for (i = 0; i < logtxtlen; i++) {
if (strncasecmp(par, logtxt[i], 3) == 0) {
loglvl |= (tmp << i);
break;
}
}
par = strtok(NULL, ", ");
}
}
int
log_open(const char *file, int foreground)
{
FILE *fp = NULL;
if (foreground) {
log_file(stdout);
} else {
if (file) {
if ((fp = fopen(file, "a+")) == 0) {
fprintf(stderr, "can't open logfile: %s\n", file);
return -1;
}
log_file(fp);
}
}
openlog(NULL, LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON);
return 0;
}
void
log_close()
{
if (logfp) {
fflush(logfp);
fclose(logfp);
}
closelog();
}
char *
log_time(char *time)
{
struct timeval tv;
struct tm *tm;
gettimeofday(&tv, NULL);
tm = localtime(&tv.tv_sec);
sprintf(time, "%04d-%02d-%02d %02d:%02d:%02d.%03ld",
tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec, tv.tv_usec/1000);
return time;
}
char *
log_txt(unsigned char lvl)
{
char *type = NULL;
if (logtxtlen > 0) {
unsigned char tmp;
int i;
tmp = 0x01;
for (i = 0; i < logtxtlen; i++) {
if (lvl == L_ALL) {
type = "ALL";
break;
}
if ((lvl & (tmp << i)) != 0x00 &&
(loglvl & (tmp << i)) != 0x00) {
type = (char *)logtxt[i];
break;
}
}
}
return type;
}
void
log_print(unsigned char lvl, const char *txt, ...)
{
char time[24];
char buf[512];
va_list ap;
va_start(ap, txt);
vsprintf(buf, txt, ap);
if ((loglvl & lvl) != 0x00) {
if (logfp) {
//~ fprintf(logfp, "%s [0x%02x %s] %s\n",
//~ log_time(time), lvl , log_txt(lvl), buf);
fprintf(logfp, "%s [%s] %s\n",
log_time(time), log_txt(lvl), buf);
fflush(logfp);
} else {
//~ syslog(LOG_INFO, "[0x%02x %s] %s\n",
//~ lvl, log_txt(lvl), txt);
syslog(LOG_INFO, "[%s] %s\n", log_txt(lvl), txt);
}
}
va_end(ap);
}
+57
View File
@@ -0,0 +1,57 @@
/*
* Copyright (C) Roland Jax 2012-2013 <roland.jax@liwest.at>
*
* This file is part of ebusd.
*
* ebusd 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.
*
* ebusd 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 ebusd. If not, see http://www.gnu.org/licenses/.
*/
#ifndef LOG_H_
#define LOG_H_
#define L_NUL 0x00
#define L_ALL 0xFF
#define L_INF 0x01
#define L_NOT 0x02
#define L_WAR 0x04
#define L_ERR 0x08
#define L_DBG 0x10
#define L_EBH 0x20
#define L_EBS 0x40
#define L_NET 0x80
#define LOGTXT "INF, NOT, WAR, ERR, DBG, EBH, EBS, NET, ALL"
static const char *logtxt[] = {"INF","NOT","WAR","ERR","DBG","EBH","EBS","NET"};
#define err_if(exp) \
if (exp) { log_print(L_ERR, "%s: %d: %s: Error %s", \
__FILE__, __LINE__, __PRETTY_FUNCTION__, strerror(errno));\
}
#define err_ret_if(exp, ret) \
if (exp) { log_print(L_ERR, "%s: %d: %s: Error %s", \
__FILE__, __LINE__, __PRETTY_FUNCTION__, strerror(errno));\
return (ret); \
}
void log_file(FILE *fp);
void log_level(char *lvl);
int log_open(const char *logfile, int foreground);
void log_close();
void log_print(unsigned char lvl, const char *txt, ...);
#endif /* LOG_H_ */