libebus project merged into ebusd project.

This commit is contained in:
Roland Jax
2014-10-27 22:28:22 +01:00
parent 809f674ea7
commit 0827c62f3f
60 changed files with 4872 additions and 49 deletions
+2 -2
View File
@@ -1,6 +1,6 @@
/INSTALL
/Makefile
/Makefile.in
Makefile
Makefile.in
/build/*
/aclocal.m4
/autom4te.cache/
+8 -31
View File
@@ -1,32 +1,9 @@
AUTOMAKE_OPTIONS = subdir-objects
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
AM_CXXFLAGS = $(LIBEBUS_CFLAGS) -I$(top_srcdir)/lib -fpic -Wall -Wextra
bin_PROGRAMS = ebusd \
ebusctl
ebusd_SOURCES = lib/appl.cpp \
lib/daemon.cpp \
lib/tcpsocket.cpp \
lib/thread.cpp \
lib/logger.cpp \
src/connection.cpp \
src/network.cpp \
src/ebusloop.cpp \
src/baseloop.cpp \
src/main.cpp
ebusd_LDADD = $(LIBEBUS_LIBS) \
-lpthread
dist_noinst_SCRIPTS = autogen.sh
ebusctl_SOURCES = lib/appl.cpp \
lib/tcpsocket.cpp \
tools/ebusctl.cpp
ebusctl_LDADD = $(LIBEBUS_LIBS)
SUBDIRS = src/libebus src/test src/libcore src/ebusd src/tools
distclean-local:
-rm -rf autom4te.cache
-rm -f aclocal.m4
-rm -f config.h.in
-rm -f configure
-rm -f Makefile.in
-rm -rf build
-1
View File
@@ -2,7 +2,6 @@
test -n "$srcdir" || srcdir=`dirname "$0"`
test -n "$srcdir" || srcdir=.
mkdir -p "$srcdir/m4"
mkdir -p "$srcdir/build"
autoreconf --force --install --verbose "$srcdir"
+14 -10
View File
@@ -1,17 +1,21 @@
AC_PREREQ([2.65])
AC_INIT([ebusd], [0.4.0], [roland.jax@liwest.at], [ebusd], [https://github.com/yuhu-/ebusd])
AC_CONFIG_SRCDIR([src/main.cpp])
AC_CONFIG_AUX_DIR([build])
AM_INIT_AUTOMAKE([1.11 -Wall -Werror foreign])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_HEADERS([config.h])
AC_PROG_CXX
PKG_CHECK_MODULES([LIBEBUS], [libebus-0.2 >= 0.2.0])
AC_CONFIG_AUX_DIR([build])
AC_CONFIG_SRCDIR([src/ebusd/main.cpp])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_FILES([Makefile
src/libebus/Makefile
src/test/Makefile
src/libcore/Makefile
src/ebusd/Makefile
src/tools/Makefile])
AM_INIT_AUTOMAKE([1.11 -Wall -Werror foreign])
AM_PROG_AR
AC_PROG_RANLIB
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
+22
View File
@@ -0,0 +1,22 @@
AM_CXXFLAGS = -fpic \
-Wall \
-Wextra \
-I$(top_srcdir)/src/libcore \
-I$(top_srcdir)/src/libebus
bin_PROGRAMS = ebusd
ebusd_SOURCES = connection.cpp \
network.cpp \
ebusloop.cpp \
baseloop.cpp \
main.cpp
ebusd_LDADD = $(top_srcdir)/src/libcore/libcore.a \
$(top_srcdir)/src/libebus/libebus.a \
-lpthread
distclean-local:
-rm -f Makefile.in
-rm -rf .libs
@@ -18,6 +18,7 @@
*/
#include "baseloop.h"
#include "configfile.h"
#include "logger.h"
#include "appl.h"
+1 -1
View File
@@ -20,7 +20,7 @@
#ifndef BASELOOP_H_
#define BASELOOP_H_
#include "libebus.h"
#include "commands.h"
#include "network.h"
#include "ebusloop.h"
+1 -1
View File
@@ -22,9 +22,9 @@
#include "tcpsocket.h"
#include "wqueue.h"
#include "message.h"
#include "notify.h"
#include "thread.h"
#include "message.h"
class Connection : public Thread
{
+2 -1
View File
@@ -20,7 +20,8 @@
#ifndef EBUSLOOP_H_
#define EBUSLOOP_H_
#include "libebus.h"
#include "bus.h"
#include "commands.h"
#include "wqueue.h"
#include "thread.h"
-1
View File
@@ -17,7 +17,6 @@
* along with ebusd. If not, see http://www.gnu.org/licenses/.
*/
#include "libebus.h"
#include "logger.h"
#include "daemon.h"
#include "appl.h"
+14
View File
@@ -0,0 +1,14 @@
AM_CXXFLAGS = -fpic \
-Wall \
-Wextra
noinst_LIBRARIES = libcore.a
libcore_a_SOURCES = appl.cpp \
daemon.cpp \
logger.cpp \
thread.cpp \
tcpsocket.cpp
distclean-local:
-rm -f Makefile.in
View File
+19
View File
@@ -0,0 +1,19 @@
AM_CXXFLAGS = -fpic \
-Wall \
-Wextra
noinst_LIBRARIES = libebus.a
libebus_a_SOURCES = result.cpp \
symbol.cpp \
port.cpp \
bus.cpp \
command.cpp \
commands.cpp \
configfile.cpp \
dump.cpp \
decode.cpp \
encode.cpp
distclean-local:
-rm -f Makefile.in
+473
View File
@@ -0,0 +1,473 @@
/*
* Copyright (C) Roland Jax 2014 <roland.jax@liwest.at>
*
* This file is part of libebus.
*
* libebus 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.
*
* libebus 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 libebus. If not, see http://www.gnu.org/licenses/.
*/
#include "bus.h"
#include <iostream>
#include <iomanip>
namespace libebus
{
BusCommand::BusCommand(const std::string commandStr, const bool isPoll)
: m_isPoll(isPoll), m_command(commandStr), m_resultCode(RESULT_OK)
{
unsigned char dstAddress = m_command[1];
if (dstAddress == BROADCAST)
m_type = broadcast;
else if (isMaster(dstAddress) == true)
m_type = masterMaster;
else
m_type = masterSlave;
pthread_mutex_init(&m_mutex, NULL);
pthread_cond_init(&m_cond, NULL);
}
BusCommand::~BusCommand()
{
pthread_mutex_destroy(&m_mutex);
pthread_cond_destroy(&m_cond);
}
const char* BusCommand::getResultCodeCStr()
{
return libebus::getResultCodeCStr(m_resultCode);
}
const std::string BusCommand::getMessageStr()
{
std::string result;
if (m_resultCode >= 0) {
if (m_type == masterSlave) {
result = m_command.getDataStr(true);
result += "00";
result += m_result.getDataStr();
result += "00";
} else {
result = "success";
}
}
else
result = "error";
return result;
}
Bus::Bus(const std::string deviceName, const bool noDeviceCheck, const long recvTimeout,
const std::string dumpFile, const long dumpSize, const bool dumpState)
: m_previousEscape(false), m_recvTimeout(recvTimeout), m_dumpState(dumpState),
m_busLocked(false), m_busPriorRetry(false)
{
m_port = new Port(deviceName, noDeviceCheck);
m_dump = new Dump(dumpFile, dumpSize);
}
Bus::~Bus()
{
if (isConnected() == true)
disconnect();
delete m_port;
delete m_dump;
}
void Bus::printBytes() const
{
unsigned char byte;
ssize_t bytes_read;
bytes_read = m_port->recv(0);
for (int i = 0; i < bytes_read; i++) {
byte = m_port->byte();
std::cout << std::nouppercase << std::hex << std::setw(2)
<< std::setfill('0') << static_cast<unsigned>(byte);
if (byte == SYN)
std::cout << std::endl;
}
}
int Bus::proceed()
{
unsigned char byte_recv;
ssize_t bytes_recv;
// fetch new message and get bus
if (m_sendBuffer.size() != 0 && m_sstr.size() == 0) {
BusCommand* busCommand = m_sendBuffer.front();
return getBus(busCommand->getCommand()[0]);
}
// wait for new data
bytes_recv = m_port->recv(0);
if (bytes_recv < 0)
return RESULT_ERR_DEVICE;
for (int i = 0; i < bytes_recv; i++) {
// fetch next byte
byte_recv = recvByte();
// store byte
return proceedCycData(byte_recv); // TODO what if more than one byte was received?
}
return RESULT_SYN;
}
int Bus::proceedCycData(const unsigned char byte)
{
if (byte != SYN) {
m_sstr.push_back_unescape(byte, m_previousEscape, false);
if (m_busLocked == true)
m_busLocked = false;
return RESULT_DATA;
}
m_previousEscape = false;
if (byte == SYN && m_sstr.size() != 0) {
// lock bus after SYN-BYTE-SYN Sequence
if (m_sstr.size() == 1 && m_busPriorRetry == false)
m_busLocked = true;
m_cycBuffer.push(m_sstr);
m_sstr.clear();
if (m_busLocked == true)
return RESULT_BUS_LOCKED;
}
return RESULT_SYN;
}
SymbolString Bus::getCycData()
{
SymbolString data;
if (m_cycBuffer.empty() == false) {
data = m_cycBuffer.front();
m_cycBuffer.pop();
}
return data;
}
int Bus::getBus(const unsigned char byte_sent)
{
unsigned char byte_recv;
ssize_t bytes_sent, bytes_recv;
// send QQ
bytes_sent = m_port->send(&byte_sent, 1);
if (bytes_sent <= 0)
return RESULT_ERR_SEND;
// receive 1 byte - must be QQ
bytes_recv = m_port->recv(0, 1);
if (bytes_recv < 0)
return RESULT_ERR_DEVICE;
// fetch next byte
byte_recv = recvByte();
// compare sent and received byte
if (bytes_recv == 1 && byte_sent == byte_recv) {
m_busPriorRetry = false;
return RESULT_BUS_ACQUIRED;
}
// store byte
int ret = proceedCycData(byte_recv);
if (ret >= 0)
return ret;
// TODO this needs to be re-designed with above proceedCycData()
// compare prior nibble for retry
if (bytes_recv == 1 && (byte_sent & 0x0F) == (byte_recv & 0x0F)) {
m_busPriorRetry = true;
return RESULT_BUS_PRIOR_RETRY;
}
m_busLocked = true;
return RESULT_ERR_BUS_LOST;
}
BusCommand* Bus::sendCommand()
{
unsigned char byte_recv;
ssize_t bytes_recv;
std::string result;
SymbolString slaveData;
int retval = RESULT_OK;
BusCommand* busCommand = m_sendBuffer.front();
m_sendBuffer.pop();
// send ZZ PB SB NN Dx CRC
SymbolString command = busCommand->getCommand();
for (size_t i = 1; i < command.size(); i++) {
retval = sendByte(command[i]);
if (retval < 0)
goto on_exit;
}
// BC -> send SYN
if (busCommand->getType() == broadcast) {
sendByte(SYN);
goto on_exit;
}
// receive ACK
bytes_recv = m_port->recv(m_recvTimeout);
if (bytes_recv > 1) {
retval = RESULT_ERR_EXTRA_DATA;
goto on_exit;
} else if (bytes_recv < 0) {
retval = RESULT_ERR_TIMEOUT;
goto on_exit;
}
byte_recv = recvByte();
// is received byte SYN?
if (byte_recv == SYN) {
retval = RESULT_ERR_SYN;
goto on_exit;
}
// is slave ACK negative?
if (byte_recv == NAK) {
// send QQ ZZ PB SB NN Dx CRC again
for (size_t i = 0; i < command.size(); i++) {
retval = sendByte(command[i]);
if (retval < 0)
goto on_exit;
}
// receive ACK
bytes_recv = m_port->recv(m_recvTimeout);
if (bytes_recv > 1) {
retval = RESULT_ERR_EXTRA_DATA;
goto on_exit;
} else if (bytes_recv < 0) {
retval = RESULT_ERR_TIMEOUT;
goto on_exit;
}
byte_recv = recvByte();
// is received byte SYN?
if (byte_recv == SYN) {
retval = RESULT_ERR_SYN;
goto on_exit;
}
// is slave ACK negative?
if (byte_recv == NAK) {
retval = sendByte(SYN);
if (retval == 0)
retval = RESULT_ERR_NAK;
goto on_exit;
}
}
// MM -> send SYN
if (busCommand->getType() == masterMaster) {
sendByte(SYN);
goto on_exit;
}
// receive NN, Dx, CRC
retval = recvSlaveDataAndCRC(slaveData);
// are calculated and received CRC equal?
if (retval == RESULT_ERR_CRC) {
// send NAK
retval = sendByte(NAK);
if (retval < 0)
goto on_exit;
// receive NN, Dx, CRC
slaveData = SymbolString();
retval = recvSlaveDataAndCRC(slaveData);
// are calculated and received CRC equal?
if (retval == RESULT_ERR_CRC) {
// send NAK
retval = sendByte(NAK);
if (retval >= 0)
retval = RESULT_ERR_CRC;
}
}
if (retval < 0)
goto on_exit;
// send ACK
retval = sendByte(ACK);
if (retval == -1) {
retval = RESULT_ERR_ACK;
goto on_exit;
}
// MS -> send SYN
sendByte(SYN);
on_exit:
// empty receive buffer
while (m_port->size() != 0)
byte_recv = recvByte();
busCommand->setResult(slaveData, retval);
return busCommand;
}
BusCommand* Bus::delCommand()
{
BusCommand* busCommand = m_sendBuffer.front();
m_sendBuffer.pop();
busCommand->setResult(SymbolString(), RESULT_ERR_BUS_LOST);
return busCommand;
}
int Bus::sendByte(const unsigned char byte_sent)
{
unsigned char byte_recv;
ssize_t bytes_sent, bytes_recv;
bytes_sent = m_port->send(&byte_sent, 1);
// receive 1 byte - must be equal
bytes_recv = m_port->recv(RECV_TIMEOUT);
if (bytes_sent != bytes_recv)
return RESULT_ERR_EXTRA_DATA;
byte_recv = recvByte();
if (byte_sent != byte_recv)
return RESULT_ERR_SEND;
return RESULT_OK;
}
unsigned char Bus::recvByte()
{
unsigned char byte_recv;
// fetch byte
byte_recv = m_port->byte();
if (m_dumpState == true)
m_dump->write((const char*) &byte_recv);
return byte_recv;
}
int Bus::recvSlaveDataAndCRC(SymbolString& result)
{
unsigned char byte_recv;
ssize_t bytes_recv;
bool previousEscape = false;
// receive NN
bytes_recv = m_port->recv(RECV_TIMEOUT, 1);
if (bytes_recv < 0)
return RESULT_ERR_TIMEOUT;
byte_recv = recvByte();
byte_recv = result.push_back_unescape(byte_recv, previousEscape);
if (previousEscape == true && byte_recv == 0)
return RESULT_ERR_ESC;
// escape sequence: get another symbol to find NN
if (previousEscape == true) {
bytes_recv = m_port->recv(RECV_TIMEOUT, 1);
if (bytes_recv < 0)
return RESULT_ERR_TIMEOUT;
byte_recv = recvByte();
byte_recv = result.push_back_unescape(byte_recv, previousEscape);
if (previousEscape == true)
return RESULT_ERR_ESC;
}
int NN = byte_recv;
// receive Dx
for (int i = 0; i < NN; i++) {
bytes_recv = m_port->recv(RECV_TIMEOUT, 1);
if (bytes_recv < 0)
return RESULT_ERR_TIMEOUT;
byte_recv = recvByte();
byte_recv = result.push_back_unescape(byte_recv, previousEscape);
if (previousEscape == true && byte_recv == 0)
return RESULT_ERR_ESC;
// escape sequence: increase NN
if (previousEscape == true)
NN++;
}
if (previousEscape == true)
return RESULT_ERR_ESC;
unsigned char crc_calc = result.getCRC();
// receive CRC
bytes_recv = m_port->recv(RECV_TIMEOUT, 1);
if (bytes_recv < 0)
return RESULT_ERR_TIMEOUT;
byte_recv = recvByte();
byte_recv = result.push_back_unescape(byte_recv, previousEscape, false);
if (previousEscape == true && byte_recv == 0)
return RESULT_ERR_ESC;
// escape sequence: get another symbol to find CRC
if (previousEscape == true) {
bytes_recv = m_port->recv(RECV_TIMEOUT, 1);
if (bytes_recv < 0)
return RESULT_ERR_TIMEOUT;
byte_recv = recvByte();
byte_recv = result.push_back_unescape(byte_recv, previousEscape);
if (previousEscape == true)
return RESULT_ERR_ESC;
}
if (crc_calc != byte_recv)
return RESULT_ERR_CRC;
return RESULT_OK;
}
} //namespace
+122
View File
@@ -0,0 +1,122 @@
/*
* Copyright (C) Roland Jax 2014 <roland.jax@liwest.at>
*
* This file is part of libebus.
*
* libebus 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.
*
* libebus 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 libebus. If not, see http://www.gnu.org/licenses/.
*/
#ifndef LIBEBUS_BUS_H_
#define LIBEBUS_BUS_H_
#include "symbol.h"
#include "result.h"
#include "port.h"
#include "dump.h"
#include <cstring>
#include <cstdlib>
#include <sstream>
#include <queue>
namespace libebus
{
// the maximum time allowed for retrieving a byte from an addressed slave
#define RECV_TIMEOUT 10000
enum CommandType { invalid, broadcast, masterMaster, masterSlave };
class BusCommand
{
public:
BusCommand(const std::string commandStr, const bool isPoll);
~BusCommand();
CommandType getType() const { return m_type; }
bool isPoll() const { return m_isPoll; }
SymbolString getCommand() const { return m_command; }
bool isErrorResult() const { return m_resultCode < 0; }
const char* getResultCodeCStr();
SymbolString getResult() const { return m_result; }
void setResult(const SymbolString result, const int resultCode) { m_result = result; m_resultCode = resultCode; }
const std::string getMessageStr();
void waitSignal() { pthread_cond_wait(&m_cond, &m_mutex); } // TODO timeout
void sendSignal() { pthread_cond_signal(&m_cond); }
private:
CommandType m_type;
bool m_isPoll;
SymbolString m_command;
SymbolString m_result;
int m_resultCode;
pthread_mutex_t m_mutex;
pthread_cond_t m_cond;
};
class Bus
{
public:
Bus(const std::string deviceName, const bool noDeviceCheck, const long recvTimeout,
const std::string dumpFile, const long dumpSize, const bool dumpState);
~Bus();
void connect() { m_port->open(); }
void disconnect() { if (m_port->isOpen() == true) m_port->close(); }
bool isConnected() { return m_port->isOpen(); }
void printBytes() const;
int proceed();
SymbolString getCycData();
void addCommand(BusCommand* busCommand) { m_sendBuffer.push(busCommand); }
int getBus(const unsigned char byte);
BusCommand* sendCommand();
BusCommand* delCommand();
void setDumpState(const bool dumpState) { m_dumpState = dumpState; }
private:
Port* m_port;
bool m_previousEscape;
SymbolString m_sstr;
std::queue<SymbolString> m_cycBuffer;
std::queue<BusCommand*> m_sendBuffer;
const long m_recvTimeout;
Dump* m_dump;
bool m_dumpState;
bool m_busLocked;
bool m_busPriorRetry;
int proceedCycData(const unsigned char byte);
int sendByte(const unsigned char byte_sent);
unsigned char recvByte();
int recvSlaveDataAndCRC(SymbolString& result);
};
} //namespace
#endif // LIBEBUS_BUS_H_
+345
View File
@@ -0,0 +1,345 @@
/*
* Copyright (C) Roland Jax 2014 <roland.jax@liwest.at>
*
* This file is part of libebus.
*
* libebus 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.
*
* libebus 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 libebus. If not, see http://www.gnu.org/licenses/.
*/
#include "command.h"
#include "decode.h"
#include "encode.h"
#include <iostream>
#include <algorithm>
#include <sstream>
#include <iomanip>
#include <vector>
#include <cstring>
namespace libebus
{
std::string Command::calcData()
{
// encode - only first entry will be encoded
// ToDo: if more parts are needed, they will be implemented
encode(m_data, m_command[13], m_command[14]);
if (m_error.length() > 0)
m_result = m_error;
return m_result;
}
std::string Command::calcResult(const cmd_t& cmd)
{
int elements = strtol(m_command[9].c_str(), NULL, 10);
if (cmd.size() > 3) {
bool found = false;
for (size_t i = 3; i < cmd.size(); i++) {
int j;
for (j = 0; j < elements; j++) {
if (m_command[10 + j*8] == cmd[i]) {
found = true;
break;
}
}
if (found == true) {
found = false;
// decode
calcSub(m_command[11 + j*8], m_command[12 + j*8],
m_command[13 + j*8], m_command[14 + j*8]);
}
}
} else {
for (int j = 0; j < elements; j++) {
// decode
calcSub(m_command[11 + j*8], m_command[12 + j*8],
m_command[13 + j*8], m_command[14 + j*8]);
}
}
if (m_error.length() > 0)
m_result = m_error;
return m_result;
}
void Command::calcSub(const std::string& part, const std::string& position,
const std::string& type, const std::string& factor)
{
std::string data;
// Master Data
if (strcasecmp(part.c_str(), "MD") == 0) {
// QQ ZZ PB SB NN
int md_pos = 10;
int md_len = strtol(m_command[7].c_str(), NULL, 10)*2;
data = m_data.substr(md_pos, md_len);
}
// Slave Acknowledge
else if (strcasecmp(part.c_str(), "SA") == 0) {
// QQ ZZ PB SB NN + Dx + CRC
int sa_pos = 10 + (strtol(m_command[7].c_str(), NULL, 10)*2) + 2;
int sa_len = 2;
data = m_data.substr(sa_pos, sa_len);
}
// Slave Data
else if (strcasecmp(part.c_str(), "SD") == 0) {
// QQ ZZ PB SB NN + Dx + CRC ACK NN
int sd_pos = 10 + (strtol(m_command[7].c_str(), NULL, 10)*2) + 6;
int sd_len = m_data.length() - (10 + (strtol(m_command[7].c_str(), NULL, 10)*2) + 6) - 4;
data = m_data.substr(sd_pos, sd_len);
}
// Master Acknowledge
else if (strcasecmp(part.c_str(), "MA") == 0) {
// QQ ZZ PB SB NN + Dx + CRC ACK NN + Dx
int ma_pos = m_data.length() - 2;
int ma_len = 2;
data = m_data.substr(ma_pos, ma_len);
}
decode(data, position, type, factor);
}
void Command::decode(const std::string& data, const std::string& position,
const std::string& type, const std::string& factor)
{
std::ostringstream result, value;
Decode* help = NULL;
// prepare position
std::string token;
std::istringstream stream(position);
std::vector<int> pos;
while (std::getline(stream, token, ',') != 0)
pos.push_back(strtol(token.c_str(), NULL, 10));
if (strcasecmp(type.c_str(), "HEX") == 0) {
if (pos.size() <= 1 || pos[1] < pos[0])
pos[1] = pos[0];
value << data.substr((pos[0]-1)*2, (pos[1]-pos[0]+1)*2);
help = new DecodeHEX(value.str());
}
else if (strcasecmp(type.c_str(), "UCH") == 0) {
value << data.substr((pos[0]-1)*2, 2);
help = new DecodeUCH(value.str(), factor);
}
else if (strcasecmp(type.c_str(), "SCH") == 0) {
value << data.substr((pos[0]-1)*2, 2);
help = new DecodeSCH(value.str(), factor);
}
else if (strcasecmp(type.c_str(), "UIN") == 0) {
value << data.substr((pos[0]-1)*2, 2) << data.substr((pos[1]-1)*2, 2);
help = new DecodeUIN(value.str(), factor);
}
else if (strcasecmp(type.c_str(), "SIN") == 0) {
value << data.substr((pos[0]-1)*2, 2) << data.substr((pos[1]-1)*2, 2);
help = new DecodeSIN(value.str(), factor);
}
else if (strcasecmp(type.c_str(), "ULG") == 0) {
value << data.substr((pos[0]-1)*2, 2) << data.substr((pos[1]-1)*2, 2)
<< data.substr((pos[2]-1)*2, 2) << data.substr((pos[3]-1)*2, 2);
help = new DecodeULG(value.str(), factor);
}
else if (strcasecmp(type.c_str(), "SLG") == 0) {
value << data.substr((pos[0]-1)*2, 2) << data.substr((pos[1]-1)*2, 2)
<< data.substr((pos[2]-1)*2, 2) << data.substr((pos[3]-1)*2, 2);
help = new DecodeSLG(value.str(), factor);
}
else if (strcasecmp(type.c_str(), "FLT") == 0) {
value << data.substr((pos[0]-1)*2, 2) << data.substr((pos[1]-1)*2, 2);
help = new DecodeFLT(value.str(), factor);
}
else if (strcasecmp(type.c_str(), "STR") == 0) {
if (pos.size() <= 1 || pos[1] < pos[0])
pos[1] = pos[0];
value << data.substr((pos[0]-1)*2, (pos[1]-pos[0]+1)*2);
help = new DecodeSTR(value.str());
}
else if (strcasecmp(type.c_str(), "BCD") == 0) {
value << data.substr((pos[0]-1)*2, 2);
help = new DecodeBCD(value.str(), factor);
}
else if (strcasecmp(type.c_str(), "D1B") == 0) {
value << data.substr((pos[0]-1)*2, 2);
help = new DecodeD1B(value.str(), factor);
}
else if (strcasecmp(type.c_str(), "D1C") == 0) {
value << data.substr((pos[0]-1)*2, 2);
help = new DecodeD1C(value.str(), factor);
}
else if (strcasecmp(type.c_str(), "D2B") == 0) {
value << data.substr((pos[0]-1)*2, 2) << data.substr((pos[1]-1)*2, 2);
help = new DecodeD2B(value.str(), factor);
}
else if (strcasecmp(type.c_str(), "D2C") == 0) {
value << data.substr((pos[0]-1)*2, 2) << data.substr((pos[1]-1)*2, 2);
help = new DecodeD2C(value.str(), factor);
}
else if (strcasecmp(type.c_str(), "BDA") == 0) {
value << data.substr((pos[0]-1)*2, 2)
<< data.substr((pos[1]-1)*2, 2)
<< data.substr((pos[2]-1)*2, 2);
help = new DecodeBDA(value.str());
}
else if (strcasecmp(type.c_str(), "HDA") == 0) {
value << data.substr((pos[0]-1)*2, 2)
<< data.substr((pos[1]-1)*2, 2)
<< data.substr((pos[2]-1)*2, 2);
help = new DecodeHDA(value.str());
}
else if (strcasecmp(type.c_str(), "BTI") == 0) {
value << data.substr((pos[0]-1)*2, 2)
<< data.substr((pos[1]-1)*2, 2)
<< data.substr((pos[2]-1)*2, 2);
help = new DecodeBTI(value.str());
}
else if (strcasecmp(type.c_str(), "HTI") == 0) {
value << data.substr((pos[0]-1)*2, 2)
<< data.substr((pos[1]-1)*2, 2)
<< data.substr((pos[2]-1)*2, 2);
help = new DecodeHTI(value.str());
}
else if (strcasecmp(type.c_str(), "BDY") == 0) {
value << data.substr((pos[0]-1)*2, 2);
help = new DecodeBDY(value.str());
}
else if (strcasecmp(type.c_str(), "HDY") == 0) {
value << data.substr((pos[0]-1)*2, 2);
help = new DecodeHDY(value.str());
}
else if (strcasecmp(type.c_str(), "TTM") == 0) {
value << data.substr((pos[0]-1)*2, 2);
help = new DecodeTTM(value.str());
}
if (help == NULL) {
result << "type '" << type.c_str() << "' not implemented!";
m_error = result.str();
} else {
result << help->decode();
if (m_result.length() > 0)
m_result += " ";
m_result += result.str();
}
delete help;
}
void Command::encode(const std::string& data, const std::string& type,
const std::string& factor)
{
std::ostringstream result;
Encode* help = NULL;
if (strcasecmp(type.c_str(), "HEX") == 0) {
help = new EncodeHEX(data);
}
else if (strcasecmp(type.c_str(), "UCH") == 0) {
help = new EncodeUCH(data, factor);
}
else if (strcasecmp(type.c_str(), "SCH") == 0) {
help = new EncodeSCH(data, factor);
}
else if (strcasecmp(type.c_str(), "UIN") == 0) {
help = new EncodeUIN(data, factor);
}
else if (strcasecmp(type.c_str(), "SIN") == 0) {
help = new EncodeSIN(data, factor);
}
else if (strcasecmp(type.c_str(), "ULG") == 0) {
help = new EncodeULG(data, factor);
}
else if (strcasecmp(type.c_str(), "SLG") == 0) {
help = new EncodeSLG(data, factor);
}
else if (strcasecmp(type.c_str(), "FLT") == 0) {
help = new EncodeSLG(data, factor);
}
else if (strcasecmp(type.c_str(), "STR") == 0) {
help = new EncodeSTR(data);
}
else if (strcasecmp(type.c_str(), "BCD") == 0) {
help = new EncodeBCD(data, factor);
}
else if (strcasecmp(type.c_str(), "D1B") == 0) {
help = new EncodeD1B(data, factor);
}
else if (strcasecmp(type.c_str(), "D1C") == 0) {
help = new EncodeD1C(data, factor);
}
else if (strcasecmp(type.c_str(), "D2B") == 0) {
help = new EncodeD2B(data, factor);
}
else if (strcasecmp(type.c_str(), "D2C") == 0) {
help = new EncodeD2C(data, factor);
}
else if (strcasecmp(type.c_str(), "BDA") == 0) {
help = new EncodeBDA(data);
}
else if (strcasecmp(type.c_str(), "HDA") == 0) {
help = new EncodeHDA(data);
}
else if (strcasecmp(type.c_str(), "BTI") == 0) {
help = new EncodeBTI(data);
}
else if (strcasecmp(type.c_str(), "HTI") == 0) {
help = new EncodeHTI(data);
}
else if (strcasecmp(type.c_str(), "BDY") == 0) {
help = new EncodeBDY(data);
}
else if (strcasecmp(type.c_str(), "HDY") == 0) {
help = new EncodeHDY(data);
}
else if (strcasecmp(type.c_str(), "TTM") == 0) {
help = new EncodeTTM(data);
}
if (help == NULL) {
result << "type '" << type.c_str() << "' not implemented!";
m_error = result.str();
} else {
result << help->encode();
if (m_result.length() > 0)
m_result += " ";
m_result += result.str();
}
delete help;
}
} //namespace
+69
View File
@@ -0,0 +1,69 @@
/*
* Copyright (C) Roland Jax 2014 <roland.jax@liwest.at>
*
* This file is part of libebus.
*
* libebus 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.
*
* libebus 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 libebus. If not, see http://www.gnu.org/licenses/.
*/
#ifndef LIBEBUS_COMMAND_H_
#define LIBEBUS_COMMAND_H_
#include <string>
#include <vector>
namespace libebus
{
typedef std::vector<std::string> cmd_t;
typedef cmd_t::const_iterator cmdCI_t;
class Command
{
public:
Command(int index, cmd_t command) : m_index(index), m_command(command) {}
Command(int index, cmd_t command, std::string data)
: m_index(index), m_command(command), m_data(data) {}
cmd_t getCommand() const { return m_command; }
void setData(const std::string& data) { m_data = data; }
std::string getData() const { return m_data; }
std::string calcData();
std::string calcResult(const cmd_t& cmd);
private:
int m_index;
cmd_t m_command;
std::string m_data;
std::string m_result;
std::string m_error;
void calcSub(const std::string& part, const std::string& position,
const std::string& type, const std::string& factor);
void decode(const std::string& data, const std::string& position,
const std::string& type, const std::string& factor);
void encode(const std::string& data, const std::string& type,
const std::string& factor);
};
} //namespace
#endif // LIBEBUS_COMMAND_H_
+246
View File
@@ -0,0 +1,246 @@
/*
* Copyright (C) Roland Jax 2014 <roland.jax@liwest.at>
*
* This file is part of libebus.
*
* libebus 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.
*
* libebus 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 libebus. If not, see http://www.gnu.org/licenses/.
*/
#include "commands.h"
#include <iostream>
#include <algorithm>
#include <sstream>
#include <iomanip>
#include <vector>
#include <cstring>
namespace libebus
{
Commands::~Commands()
{
for (mapCI_t iter = m_polDB.begin(); iter != m_polDB.end(); ++iter)
delete iter->second;
m_polDB.clear();
for (mapCI_t iter = m_cycDB.begin(); iter != m_cycDB.end(); ++iter)
delete iter->second;
m_cycDB.clear();
m_cmdDB.clear();
}
void Commands::addCommand(const cmd_t& command)
{
m_cmdDB.push_back(command);
if (strcasecmp(command[0].c_str(),"C") == 0) {
Command* cmd = new Command(m_cmdDB.size()-1, command);
m_cycDB.insert(pair_t(m_cmdDB.size()-1, cmd));
}
if (strcasecmp(command[0].c_str(),"P") == 0) {
Command* cmd = new Command(m_cmdDB.size()-1, command);
m_polDB.insert(pair_t(m_cmdDB.size()-1, cmd));
}
}
void Commands::printCommands() const
{
if (m_cmdDB.size() == 0)
return;
for (cmdDBCI_t i = m_cmdDB.begin(); i != m_cmdDB.end(); i++) {
printCommand(*i);
std::cout << std::endl;
}
}
int Commands::findCommand(const std::string& data) const
{
// no commands definend
if (m_cmdDB.size() == 0)
return -2;
// preapre string for searching command
std::string token;
std::istringstream isstr(data);
std::vector<std::string> cmd;
// split stream
while (std::getline(isstr, token, ' ') != 0)
cmd.push_back(token);
std::size_t index;
cmdDBCI_t i = m_cmdDB.begin();
// walk through commands - GET
if (strcasecmp(cmd[0].c_str(), "GET") == 0) {
for (index = 0; i != m_cmdDB.end(); i++, index++) {
// empty line
if ((*i).size() == 0)
continue;
if (((strcasecmp((*i)[0].c_str(), "R") == 0)
|| (strcasecmp((*i)[0].c_str(), "P") == 0))
&& (strcasecmp((*i)[1].c_str(), cmd[1].c_str()) == 0)
&& (strcasecmp((*i)[2].c_str(), cmd[2].c_str()) == 0))
return index;
}
// walk through commands - SET, CYC
} else {
// correct type
if (strcasecmp(cmd[0].c_str(), "SET") == 0)
cmd[0] = "W";
else if (strcasecmp(cmd[0].c_str(), "CYC") == 0)
cmd[0] = "C";
for (index = 0; i != m_cmdDB.end(); i++, index++) {
// empty line
if ((*i).size() == 0)
continue;
if (strcasecmp((*i)[0].c_str(), cmd[0].c_str()) == 0 &&
strcasecmp((*i)[1].c_str(), cmd[1].c_str()) == 0 &&
strcasecmp((*i)[2].c_str(), cmd[2].c_str()) == 0)
return index;
}
}
// command not found
return -1;
}
std::string Commands::getEbusCommand(const int index) const
{
cmd_t command = m_cmdDB.at(index);
std::string cmd(command[5]);
cmd += command[6];
std::stringstream sstr;
sstr << std::setw(2) << std::hex << std::setfill('0') << command[7];
cmd += sstr.str();
cmd += command[8];
return cmd;
}
int Commands::storeCycData(const std::string& data) const
{
// no commands defined
if (m_cycDB.size() == 0)
return -2;
// search skipped - string too short
if (data.length() < 10)
return -3;
// prepare string for searching command
std::string search(data.substr(2, 8 + strtol(data.substr(8,2).c_str(), NULL, 16) * 2));
mapCI_t iter = m_cycDB.begin();
// walk through commands
for (; iter != m_cycDB.end(); iter++) {
std::string command = getEbusCommand(iter->first);
// skip wrong search string length
if (command.length() > search.length())
continue;
if (strcasecmp(command.c_str(), search.substr(0,command.length()).c_str()) == 0) {
iter->second->setData(data);
return iter->first;
}
}
// command not found
return -1;
}
std::string Commands::getCycData(int index) const
{
mapCI_t iter = m_cycDB.find(index);
if (iter != m_cycDB.end())
return iter->second->getData();
else
return "";
}
int Commands::nextPolCommand()
{
size_t index = 0;
m_polIndex++;
if (m_polIndex == m_polDB.size())
m_polIndex = 0;
mapCI_t iter = m_polDB.begin();
for (; iter != m_polDB.end(); iter++, index++)
if (index == m_polIndex)
return iter->first;
return -1;
}
void Commands::storePolData(const std::string& data) const
{
// prepare string for searching command
std::string search(data.substr(2, 8 + strtol(data.substr(8,2).c_str(), NULL, 16) * 2));
mapCI_t iter = m_polDB.begin();
// walk through commands
for (; iter != m_polDB.end(); iter++) {
std::string command = getEbusCommand(iter->first);
// skip wrong search string length
if (command.length() > search.length())
continue;
if (strcasecmp(command.c_str(), search.substr(0,command.length()).c_str()) == 0)
iter->second->setData(data);
}
}
std::string Commands::getPolData(int index) const
{
mapCI_t iter = m_polDB.find(index);
if (iter != m_polDB.end())
return iter->second->getData();
else
return "";
}
void Commands::printCommand(const cmd_t& command) const
{
if (command.size() == 0)
return;
for (cmdCI_t i = command.begin(); i != command.end(); i++)
std::cout << *i << ';';
}
} //namespace
+81
View File
@@ -0,0 +1,81 @@
/*
* Copyright (C) Roland Jax 2014 <roland.jax@liwest.at>
*
* This file is part of libebus.
*
* libebus 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.
*
* libebus 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 libebus. If not, see http://www.gnu.org/licenses/.
*/
#ifndef LIBEBUS_COMMANDS_H_
#define LIBEBUS_COMMANDS_H_
#include "command.h"
#include <string>
#include <vector>
#include <map>
namespace libebus
{
typedef std::vector<cmd_t> cmdDB_t;
typedef cmdDB_t::const_iterator cmdDBCI_t;
typedef std::map<int, Command*> map_t;
typedef map_t::const_iterator mapCI_t;
typedef std::pair<int, Command*> pair_t;
class Commands
{
public:
Commands() : m_polIndex(-1) {}
~Commands();
void addCommand(const cmd_t& command);
void printCommands() const;
std::size_t sizeCmdDB() const { return m_cmdDB.size(); }
std::size_t sizeCycDB() const { return m_cycDB.size(); }
std::size_t sizePolDB() const { return m_polDB.size(); }
cmd_t const& operator[](const std::size_t& index) const { return m_cmdDB[index]; }
int findCommand(const std::string& data) const;
std::string getCmdType(const int index) const { return std::string(m_cmdDB.at(index)[0]); }
std::string getEbusType(const int index) const { return std::string(m_cmdDB.at(index)[4]); }
std::string getEbusCommand(const int index) const;
int storeCycData(const std::string& data) const;
std::string getCycData(int index) const;
int nextPolCommand();
void storePolData(const std::string& data) const;
std::string getPolData(int index) const;
private:
cmdDB_t m_cmdDB;
map_t m_cycDB;
map_t m_polDB;
size_t m_polIndex;
void printCommand(const cmd_t& command) const;
};
} //namespace
#endif // LIBEBUS_COMMANDS_H_
+137
View File
@@ -0,0 +1,137 @@
/*
* Copyright (C) Roland Jax 2014 <roland.jax@liwest.at>
*
* This file is part of libebus.
*
* libebus 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.
*
* libebus 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 libebus. If not, see http://www.gnu.org/licenses/.
*/
#include "configfile.h"
#include <sstream>
#include <fstream>
#include <dirent.h>
namespace libebus
{
void ConfigFileCSV::readFile(std::istream& is, Commands& commands)
{
std::string line;
// read lines
while (std::getline(is, line) != 0) {
cmd_t row;
std::string column;
std::istringstream isstr(line);
// walk through columns
while (std::getline(isstr, column, ';') != 0)
row.push_back(column);
// skip empty and commented rows
if (row.empty() == true || row[0][0] == '#')
continue;
commands.addCommand(row);
}
};
void ConfigFileXML::readFile(std::istream& is, Commands& commands)
{
; // ToDo: Implamantion for xml files
}
ConfigCommands::ConfigCommands(const std::string path, const FileType type)
{
m_path = path;
m_configfile = NULL;
setType(type);
addFiles(m_path, m_extension);
}
void ConfigCommands::setType(const FileType type)
{
if (m_configfile != NULL)
delete m_configfile;
switch (type) {
case CSV:
m_configfile = new ConfigFileCSV();
m_extension = "csv";
break;
case XML:
m_configfile = new ConfigFileXML();
m_extension = "xml";
break;
};
};
Commands* ConfigCommands::getCommands()
{
Commands* commands = new Commands();
std::vector<std::string>::const_iterator i = m_files.begin();
for(; i != m_files.end(); i++) {
std::fstream file((*i).c_str(), std::ios::in);
if(file.is_open() == true) {
m_configfile->readFile(file, *commands);
file.close();
}
}
return commands;
};
void ConfigCommands::addFiles(const std::string path, const std::string extension)
{
DIR* dir = opendir(path.c_str());
if (dir == NULL)
return;
dirent* d = readdir(dir);
while (d != NULL) {
if (d->d_type == DT_DIR) {
std::string fn = d->d_name;
if (fn != "." && fn != "..") {
const std::string p = path + "/" + d->d_name;
addFiles(p, extension);
}
} else if (d->d_type == DT_REG) {
std::string fn = d->d_name;
if (fn.find(extension, (fn.length() - extension.length())) != std::string::npos) {
const std::string p = path + "/" + d->d_name;
m_files.push_back(p);
}
}
d = readdir(dir);
}
closedir(dir);
};
} //namespace
+86
View File
@@ -0,0 +1,86 @@
/*
* Copyright (C) Roland Jax 2014 <roland.jax@liwest.at>
*
* This file is part of libebus.
*
* libebus 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.
*
* libebus 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 libebus. If not, see http://www.gnu.org/licenses/.
*/
#ifndef LIBEBUS_CONFIGFILE_H_
#define LIBEBUS_CONFIGFILE_H_
#include "commands.h"
#include <string>
#include <vector>
namespace libebus
{
enum FileType { CSV, XML };
class ConfigFile
{
public:
virtual ~ConfigFile() {}
virtual void readFile(std::istream& is, Commands& commands) = 0;
};
class ConfigFileCSV : public ConfigFile
{
public:
~ConfigFileCSV() {}
void readFile(std::istream& is, Commands& commands);
};
class ConfigFileXML : public ConfigFile
{
public:
~ConfigFileXML() {}
void readFile(std::istream& is, Commands& commands);
};
class ConfigCommands
{
public:
ConfigCommands(const std::string path, const FileType type);
~ConfigCommands() { delete m_configfile; }
void setType(const FileType type);
Commands* getCommands();
private:
ConfigFile* m_configfile;
std::string m_path;
std::string m_extension;
std::vector<std::string> m_files;
void addFiles(const std::string path, const std::string extension);
};
} //namespace
#endif // LIBEBUS_CONFIGFILE_H_
+353
View File
@@ -0,0 +1,353 @@
/*
* Copyright (C) Roland Jax 2014 <roland.jax@liwest.at>
* crc calculations from http://www.mikrocontroller.net/topic/75698
*
* This file is part of libebus.
*
* libebus 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.
*
* libebus 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 libebus. If not, see http://www.gnu.org/licenses/.
*/
#include "decode.h"
#include <cstdlib>
#include <sstream>
#include <iomanip>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
namespace libebus
{
Decode::Decode(const std::string& data, const std::string& factor)
: m_data(data)
{
if ((factor.find_first_not_of("0123456789.") == std::string::npos) == true)
m_factor = static_cast<float>(strtod(factor.c_str(), NULL));
else
m_factor = 1.0;
}
std::string DecodeHEX::decode()
{
std::ostringstream result;
for (size_t i = 0; i < m_data.length()/2; i++)
result << m_data.substr(i*2, 2) << " ";
return result.str().substr(0, result.str().length()-1);
}
std::string DecodeUCH::decode()
{
std::stringstream ss;
ss << std::hex << m_data;
unsigned short x;
ss >> x;
std::ostringstream result;
result << std::setprecision(3) << std::fixed << static_cast<float>(x * m_factor);
return result.str();
}
std::string DecodeSCH::decode()
{
std::stringstream ss;
ss << std::hex << m_data;
unsigned short x;
ss >> x;
std::ostringstream result;
if ((x & 0x80) == 0x80)
result << std::setprecision(3) << std::fixed
<< static_cast<float>(static_cast<short>(- ( ((unsigned char) (~ x)) + 1) ) * m_factor);
else
result << std::setprecision(3) << std::fixed
<< static_cast<float>(static_cast<short>(x) * m_factor);
return result.str();
}
std::string DecodeUIN::decode()
{
std::stringstream ss;
ss << std::hex << m_data;
unsigned short x;
ss >> x;
std::ostringstream result;
result << std::setprecision(3) << std::fixed << static_cast<float>(x * m_factor);
return result.str();
}
std::string DecodeSIN::decode()
{
std::stringstream ss;
ss << std::hex << m_data;
unsigned short x;
ss >> x;
std::ostringstream result;
result << std::setprecision(3) << std::fixed << static_cast<float>(static_cast<short>(x) * m_factor);
return result.str();
}
std::string DecodeULG::decode()
{
std::stringstream ss;
ss << std::hex << m_data;
unsigned int x;
ss >> x;
std::ostringstream result;
result << std::setprecision(3) << std::fixed << static_cast<float>(x * m_factor);
return result.str();
}
std::string DecodeSLG::decode()
{
std::stringstream ss;
ss << std::hex << m_data;
unsigned int x;
ss >> x;
std::ostringstream result;
result << std::setprecision(3) << std::fixed <<static_cast<float>(static_cast<int>(x) * m_factor);
return result.str();
}
std::string DecodeFLT::decode()
{
std::stringstream ss;
ss << std::hex << m_data;
short x;
ss >> x;
std::ostringstream result;
result << std::setprecision(3) << std::fixed << static_cast<float>(x / 1000.0 * m_factor);
return result.str();
}
std::string DecodeSTR::decode()
{
std::ostringstream result;
for (size_t i = 0; i <= m_data.length()/2; i++) {
char tmp = static_cast<char>(strtol(m_data.substr(i*2, 2).c_str(), NULL, 16));
if (tmp == 0x00) tmp = 0x20;
result << tmp;
}
return result.str().substr(0, result.str().length()-1);
}
std::string DecodeBCD::decode()
{
std::ostringstream result;
unsigned char src = strtol(m_data.c_str(), NULL, 16);
if ((src & 0x0F) > 0x09 || ((src >> 4) & 0x0F) > 0x09)
result << static_cast<short>(0xFF);
else
result << static_cast<short>(( ( ((src & 0xF0) >> 4) * 10) + (src & 0x0F) ) * m_factor);
return result.str();
}
std::string DecodeD1B::decode()
{
std::ostringstream result;
unsigned char src = strtol(m_data.c_str(), NULL, 16);
if ((src & 0x80) == 0x80)
result << static_cast<short>((- ( ((unsigned char) (~ src)) + 1) ) * m_factor);
else
result << static_cast<short>(src * m_factor);
return result.str();
}
std::string DecodeD1C::decode()
{
std::ostringstream result;
unsigned char src = strtol(m_data.c_str(), NULL, 16);
if (src > 0xC8)
result << static_cast<float>(0xFF);
else
result << static_cast<float>((src / 2.0) * m_factor);
return result.str();
}
std::string DecodeD2B::decode()
{
std::ostringstream result;
unsigned char src_lsb = static_cast<char>(strtol(m_data.substr(0, 2).c_str(), NULL, 16));
unsigned char src_msb = static_cast<char>(strtol(m_data.substr(2, 2).c_str(), NULL, 16));
if ((src_msb & 0x80) == 0x80)
result << static_cast<float>
((- ( ((unsigned char) (~ src_msb)) +
( ( ((unsigned char) (~ src_lsb)) + 1) / 256.0) ) ) * m_factor);
else
result << static_cast<float>((src_msb + (src_lsb / 256.0)) * m_factor);
return result.str();
}
std::string DecodeD2C::decode()
{
std::ostringstream result;
unsigned char src_lsb = static_cast<char>(strtol(m_data.substr(0, 2).c_str(), NULL, 16));
unsigned char src_msb = static_cast<char>(strtol(m_data.substr(2, 2).c_str(), NULL, 16));
if ((src_msb & 0x80) == 0x80)
result << static_cast<float>
((- ( ( ( ((unsigned char) (~ src_msb)) * 16.0) ) +
( ( ((unsigned char) (~ src_lsb)) & 0xF0) >> 4) +
( ( ( ((unsigned char) (~ src_lsb)) & 0x0F) +1 ) / 16.0) ) ) * m_factor);
else
result << static_cast<float>(( (src_msb * 16.0) + ((src_lsb & 0xF0) >> 4) +
((src_lsb & 0x0F) / 16.0) ) * m_factor);
return result.str();
}
std::string DecodeBDA::decode()
{
std::ostringstream result;
Decode* decode;
short array[3];
for (int i = 0; i < 3; i++) {
decode = new DecodeBCD(m_data.substr(i*2, 2), "1.0");
array[i] = static_cast<short>(strtol(decode->decode().c_str(), NULL, 10));
delete decode;
}
result << std::setw(2) << std::setfill('0') << array[0] << "."
<< std::setw(2) << std::setfill('0') << array[1] << "."
<< array[2] + 2000;
return result.str();
}
std::string DecodeHDA::decode()
{
std::ostringstream result;
short dd = static_cast<short>(strtol(m_data.substr(0, 2).c_str(), NULL, 16));
short mm = static_cast<short>(strtol(m_data.substr(2, 2).c_str(), NULL, 16));
short yy = static_cast<short>(strtol(m_data.substr(4, 2).c_str(), NULL, 16));
result << std::setw(2) << std::setfill('0') << dd << "."
<< std::setw(2) << std::setfill('0') << mm << "."
<< yy + 2000;
return result.str();
}
std::string DecodeBTI::decode()
{
std::ostringstream result;
Decode* decode;
short array[3];
for (int i = 0; i < 3; i++) {
decode = new DecodeBCD(m_data.substr(i*2, 2), "1.0");
array[i] = static_cast<short>(strtol(decode->decode().c_str(), NULL, 10));
delete decode;
}
result << std::setw(2) << std::setfill('0') << array[0] << ":"
<< std::setw(2) << std::setfill('0') << array[1] << ":"
<< std::setw(2) << std::setfill('0') << array[2];
return result.str();
}
std::string DecodeHTI::decode()
{
std::ostringstream result;
short hh = static_cast<short>(strtol(m_data.substr(0, 2).c_str(), NULL, 16));
short mm = static_cast<short>(strtol(m_data.substr(2, 2).c_str(), NULL, 16));
short ss = static_cast<short>(strtol(m_data.substr(4, 2).c_str(), NULL, 16));
result << std::setw(2) << std::setfill('0') << hh << ":"
<< std::setw(2) << std::setfill('0') << mm << ":"
<< std::setw(2) << std::setfill('0') << ss;
return result.str();
}
std::string DecodeBDY::decode()
{
const char *days[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", "Err"};
std::ostringstream result;
short day = static_cast<short>(strtol(m_data.c_str(), NULL, 16));
if (day < 0 || day > 6)
day = 7;
result << days[day];
return result.str();
}
std::string DecodeHDY::decode()
{
const char *days[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", "Err"};
std::ostringstream result;
short day = static_cast<short>(strtol(m_data.c_str(), NULL, 16)) - 1;
if (day < 0 || day > 6)
day = 7;
result << days[day];
return result.str();
}
std::string DecodeTTM::decode()
{
std::ostringstream result;
short hh = static_cast<short>(strtol(m_data.c_str(), NULL, 16)) / 6;
short mm = static_cast<short>(strtol(m_data.c_str(), NULL, 16)) % 6 * 10;
result << std::setw(2) << std::setfill('0') << hh << ":"
<< std::setw(2) << std::setfill('0') << mm;
return result.str();
}
} //namespace
+292
View File
@@ -0,0 +1,292 @@
/*
* Copyright (C) Roland Jax 2014 <roland.jax@liwest.at>
* crc calculations from http://www.mikrocontroller.net/topic/75698
*
* This file is part of libebus.
*
* libebus 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.
*
* libebus 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 libebus. If not, see http://www.gnu.org/licenses/.
*/
#ifndef LIBEBUS_DECODE_H_
#define LIBEBUS_DECODE_H_
#include <string>
namespace libebus
{
class Decode
{
public:
Decode(const std::string& data, const std::string& factor = "");
virtual ~Decode() {}
virtual std::string decode() = 0;
protected:
std::string m_data;
float m_factor;
};
class DecodeHEX : public Decode
{
public:
DecodeHEX(const std::string& data) : Decode(data) {}
~DecodeHEX() {}
std::string decode();
};
class DecodeUCH : public Decode
{
public:
DecodeUCH(const std::string& data, const std::string& factor)
: Decode(data, factor) {}
~DecodeUCH() {}
std::string decode();
};
class DecodeSCH : public Decode
{
public:
DecodeSCH(const std::string& data, const std::string& factor)
: Decode(data, factor) {}
~DecodeSCH() {}
std::string decode();
};
class DecodeUIN : public Decode
{
public:
DecodeUIN(const std::string& data, const std::string& factor)
: Decode(data, factor) {}
~DecodeUIN() {}
std::string decode();
};
class DecodeSIN : public Decode
{
public:
DecodeSIN(const std::string& data, const std::string& factor)
: Decode(data, factor) {}
~DecodeSIN() {}
std::string decode();
};
class DecodeULG : public Decode
{
public:
DecodeULG(const std::string& data, const std::string& factor)
: Decode(data, factor) {}
~DecodeULG() {}
std::string decode();
};
class DecodeSLG : public Decode
{
public:
DecodeSLG(const std::string& data, const std::string& factor)
: Decode(data, factor) {}
~DecodeSLG() {}
std::string decode();
};
class DecodeFLT : public Decode
{
public:
DecodeFLT(const std::string& data, const std::string& factor)
: Decode(data, factor) {}
~DecodeFLT() {}
std::string decode();
};
class DecodeSTR : public Decode
{
public:
DecodeSTR(std::string data) : Decode(data) {}
~DecodeSTR() {}
std::string decode();
};
class DecodeBCD : public Decode
{
public:
DecodeBCD(const std::string& data, const std::string& factor)
: Decode(data, factor) {}
~DecodeBCD() {}
std::string decode();
};
class DecodeD1B : public Decode
{
public:
DecodeD1B(const std::string& data, const std::string& factor)
: Decode(data, factor) {}
~DecodeD1B() {}
std::string decode();
};
class DecodeD1C : public Decode
{
public:
DecodeD1C(const std::string& data, const std::string& factor)
: Decode(data, factor) {}
~DecodeD1C() {}
std::string decode();
};
class DecodeD2B : public Decode
{
public:
DecodeD2B(const std::string& data, const std::string& factor)
: Decode(data, factor) {}
~DecodeD2B() {}
std::string decode();
};
class DecodeD2C : public Decode
{
public:
DecodeD2C(const std::string& data, const std::string& factor)
: Decode(data, factor) {}
~DecodeD2C() {}
std::string decode();
};
class DecodeBDA : public Decode
{
public:
DecodeBDA(const std::string& data) : Decode(data) {}
~DecodeBDA() {}
std::string decode();
};
class DecodeHDA : public Decode
{
public:
DecodeHDA(const std::string& data) : Decode(data) {}
~DecodeHDA() {}
std::string decode();
};
class DecodeBTI : public Decode
{
public:
DecodeBTI(const std::string& data) : Decode(data) {}
~DecodeBTI() {}
std::string decode();
};
class DecodeHTI : public Decode
{
public:
DecodeHTI(const std::string& data) : Decode(data) {}
~DecodeHTI() {}
std::string decode();
};
class DecodeBDY : public Decode
{
public:
DecodeBDY(const std::string& data) : Decode(data) {}
~DecodeBDY() {}
std::string decode();
};
class DecodeHDY : public Decode
{
public:
DecodeHDY(const std::string& data) : Decode(data) {}
~DecodeHDY() {}
std::string decode();
};
class DecodeTTM : public Decode
{
public:
DecodeTTM(const std::string& data) : Decode(data) {}
~DecodeTTM() {}
std::string decode();
};
} //namespace
#endif // LIBEBUS_DECODE_H_
+53
View File
@@ -0,0 +1,53 @@
/*
* Copyright (C) Roland Jax 2014 <roland.jax@liwest.at>
*
* This file is part of libebus.
*
* libebus 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.
*
* libebus 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 libebus. If not, see http://www.gnu.org/licenses/.
*/
#include "dump.h"
#include <fstream>
#include <cstdio>
namespace libebus
{
int Dump::write(const char* byte)
{
int ret = 0;
std::ofstream fs(m_filename.c_str(), std::ios::out | std::ios::binary | std::ios::app);
if (fs == 0)
return -1;
fs.write(byte, 1);
if (fs.tellp() >= m_filesize * 1024) {
std::string oldfile;
oldfile += m_filename;
oldfile += ".old";
ret = rename(m_filename.c_str(), oldfile.c_str());
}
fs.close();
return ret;
}
} //namespace
+50
View File
@@ -0,0 +1,50 @@
/*
* Copyright (C) Roland Jax 2014 <roland.jax@liwest.at>
*
* This file is part of libebus.
*
* libebus 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.
*
* libebus 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 libebus. If not, see http://www.gnu.org/licenses/.
*/
#ifndef LIBEBUS_DUMP_H_
#define LIBEBUS_DUMP_H_
#include <string>
namespace libebus
{
class Dump
{
public:
Dump(std::string filename, long filesize)
: m_filename(filename), m_filesize(filesize) {}
int write(const char* byte);
void setFilename(const std::string& filename) { m_filename = filename; }
void setFilesize(const long filesize) { m_filesize = filesize; }
private:
std::string m_filename;
long m_filesize;
};
} //namespace
#endif // LIBEBUS_DUMP_H_
+370
View File
@@ -0,0 +1,370 @@
/*
* Copyright (C) Roland Jax 2014 <roland.jax@liwest.at>
* crc calculations from http://www.mikrocontroller.net/topic/75698
*
* This file is part of libebus.
*
* libebus 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.
*
* libebus 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 libebus. If not, see http://www.gnu.org/licenses/.
*/
#include "encode.h"
#include <cstdlib>
#include <sstream>
#include <iomanip>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
namespace libebus
{
Encode::Encode(const std::string& data, const std::string& factor)
: m_data(data)
{
if ((factor.find_first_not_of("0123456789.") == std::string::npos) == true)
m_factor = static_cast<float>(strtod(factor.c_str(), NULL));
else
m_factor = 1.0;
}
std::string EncodeHEX::encode()
{
m_data.erase(std::remove_if(m_data.begin(), m_data.end(), isspace), m_data.end());
return m_data;
}
std::string EncodeUCH::encode()
{
std::ostringstream result;
unsigned short src = static_cast<unsigned short>(strtod(m_data.c_str(), NULL) / m_factor);
result << std::setw(2) << std::hex << std::setfill('0') << src;
return result.str().substr(result.str().length()-2,2);
}
std::string EncodeSCH::encode()
{
std::ostringstream result;
short src = static_cast<short>(strtod(m_data.c_str(), NULL) / m_factor);
if (src < -127 || src > 127)
result << std::setw(2) << std::hex << std::setfill('0')
<< static_cast<unsigned>(0x80);
else
result << std::setw(2) << std::hex << std::setfill('0')
<< static_cast<unsigned>(src);
return result.str().substr(result.str().length()-2,2);
}
std::string EncodeUIN::encode()
{
std::ostringstream result;
unsigned short src = static_cast<unsigned short>(strtod(m_data.c_str(), NULL) / m_factor);
result << std::setw(4) << std::hex << std::setfill('0') << src;
return result.str().substr(2,2) + result.str().substr(0,2);
}
std::string EncodeSIN::encode()
{
std::ostringstream result;
short src = static_cast<short>(strtod(m_data.c_str(), NULL) / m_factor);
result << std::setw(4) << std::hex << std::setfill('0') << src;
return result.str().substr(2,2) + result.str().substr(0,2);
}
std::string EncodeULG::encode()
{
std::ostringstream result;
unsigned long src = static_cast<unsigned long>(strtod(m_data.c_str(), NULL) / m_factor);
result << std::setw(8) << std::hex << std::setfill('0') << src;
return result.str().substr(6,2) + result.str().substr(4,2) +
result.str().substr(2,2) + result.str().substr(0,2);
}
std::string EncodeSLG::encode()
{
std::ostringstream result;
int src = static_cast<int>(strtod(m_data.c_str(), NULL) / m_factor);
result << std::setw(8) << std::hex << std::setfill('0') << src;
return result.str().substr(6,2) + result.str().substr(4,2) +
result.str().substr(2,2) + result.str().substr(0,2);
}
std::string EncodeFLT::encode()
{
std::ostringstream result;
short src = static_cast<short>(strtod(m_data.c_str(), NULL) * 1000.0 / m_factor);
result << std::setw(4) << std::hex << std::setfill('0') << src;
return result.str().substr(2,2) + result.str().substr(0,2);
}
std::string EncodeSTR::encode()
{
std::ostringstream result;
for (size_t i = 0; i < m_data.length(); i++)
result << std::setw(2) << std::hex << std::setfill('0') << static_cast<short>(m_data[i]);
return result.str();
}
std::string EncodeBCD::encode()
{
std::ostringstream result;
short src = static_cast<short>(strtod(m_data.c_str(), NULL) / m_factor);
if (src > 99)
result << std::setw(2) << std::hex << std::setfill('0')
<< static_cast<unsigned>(0xFF);
else
result << std::setw(2) << std::hex << std::setfill('0')
<< static_cast<unsigned>( ((src / 10) << 4) | (src % 10) );
return result.str().substr(result.str().length()-2,2);
}
std::string EncodeD1B::encode()
{
std::ostringstream result;
short src = static_cast<short>(strtod(m_data.c_str(), NULL) / m_factor);
if (src < -127 || src > 127)
result << std::setw(2) << std::hex << std::setfill('0')
<< static_cast<unsigned>(0x80);
else
result << std::setw(2) << std::hex << std::setfill('0')
<< static_cast<unsigned>(src);
return result.str().substr(result.str().length()-2,2);
}
std::string EncodeD1C::encode()
{
std::ostringstream result;
float src = static_cast<float>(strtod(m_data.c_str(), NULL) / m_factor);
if (src < 0.0 || src > 100.0)
result << std::setw(2) << std::hex << std::setfill('0')
<< static_cast<unsigned>(0xFF);
else
result << std::setw(2) << std::hex << std::setfill('0')
<< static_cast<unsigned>(src * 2.0);
return result.str();
}
std::string EncodeD2B::encode()
{
std::ostringstream result;
float src = static_cast<float>(strtod(m_data.c_str(), NULL) / m_factor);
if (src < -127.999 || src > 127.999) {
result << std::setw(2) << std::hex << std::setfill('0')
<< static_cast<unsigned>(0x80)
<< std::setw(2) << std::hex << std::setfill('0')
<< static_cast<unsigned>(0x00);
} else {
unsigned char tgt_lsb = static_cast<unsigned>((src - ((short) src)) * 256.0);
unsigned char tgt_msb;
if (src < 0.0 && tgt_lsb != 0x00)
tgt_msb = static_cast<unsigned>((short) src - 1);
else
tgt_msb = static_cast<unsigned>((short) src);
result << std::setw(2) << std::hex << std::setfill('0')
<< static_cast<unsigned>(tgt_msb)
<< std::setw(2) << std::hex << std::setfill('0')
<< static_cast<unsigned>(tgt_lsb);
}
return result.str();
}
std::string EncodeD2C::encode()
{
std::ostringstream result;
float src = static_cast<float>(strtod(m_data.c_str(), NULL) / m_factor);
if (src < -2047.999 || src > 2047.999) {
result << std::setw(2) << std::hex << std::setfill('0')
<< static_cast<unsigned>(0x80)
<< std::setw(2) << std::hex << std::setfill('0')
<< static_cast<unsigned>(0x00);
} else {
unsigned char tgt_lsb = static_cast<unsigned>(
((unsigned char) ( ((short) src) % 16) << 4) +
((unsigned char) ( (src - ((short) src)) * 16.0)) );
unsigned char tgt_msb;
if (src < 0.0 && tgt_lsb != 0x00)
tgt_msb = static_cast<unsigned>((short) (src / 16.0) - 1);
else
tgt_msb = static_cast<unsigned>((short) src / 16.0);
result << std::setw(2) << std::hex << std::setfill('0')
<< static_cast<unsigned>(tgt_msb)
<< std::setw(2) << std::hex << std::setfill('0')
<< static_cast<unsigned>(tgt_lsb);
}
return result.str();
}
std::string EncodeBDA::encode()
{
// prepare data
std::string token;
std::istringstream stream(m_data);
std::vector<std::string> data;
while (std::getline(stream, token, '.') != 0)
data.push_back(token);
std::ostringstream result;
result << std::setw(2) << std::dec << std::setfill('0')
<< static_cast<short>(strtod(data[0].c_str(), NULL))
<< std::setw(2) << std::dec << std::setfill('0')
<< static_cast<short>(strtod(data[1].c_str(), NULL))
<< std::setw(2) << std::dec << std::setfill('0')
<< static_cast<short>(strtod(data[2].c_str(), NULL) - 2000);
return result.str();
}
std::string EncodeHDA::encode()
{
// prepare data
std::string token;
std::istringstream stream(m_data);
std::vector<std::string> data;
while (std::getline(stream, token, '.') != 0)
data.push_back(token);
std::ostringstream result;
result << std::setw(2) << std::hex << std::setfill('0')
<< static_cast<short>(strtod(data[0].c_str(), NULL))
<< std::setw(2) << std::hex << std::setfill('0')
<< static_cast<short>(strtod(data[1].c_str(), NULL))
<< std::setw(2) << std::hex << std::setfill('0')
<< static_cast<short>(strtod(data[2].c_str(), NULL) - 2000);
return result.str();
}
std::string EncodeBTI::encode()
{
// prepare data
std::string token;
std::istringstream stream(m_data);
std::vector<std::string> data;
while (std::getline(stream, token, ':') != 0)
data.push_back(token);
std::ostringstream result;
result << std::setw(2) << std::dec << std::setfill('0')
<< static_cast<short>(strtod(data[0].c_str(), NULL))
<< std::setw(2) << std::dec << std::setfill('0')
<< static_cast<short>(strtod(data[1].c_str(), NULL))
<< std::setw(2) << std::dec << std::setfill('0')
<< static_cast<short>(strtod(data[2].c_str(), NULL));
return result.str();
}
std::string EncodeHTI::encode()
{
// prepare data
std::string token;
std::istringstream stream(m_data);
std::vector<std::string> data;
while (std::getline(stream, token, ':') != 0)
data.push_back(token);
std::ostringstream result;
result << std::setw(2) << std::hex << std::setfill('0')
<< static_cast<short>(strtod(data[0].c_str(), NULL))
<< std::setw(2) << std::hex << std::setfill('0')
<< static_cast<short>(strtod(data[1].c_str(), NULL))
<< std::setw(2) << std::hex << std::setfill('0')
<< static_cast<short>(strtod(data[2].c_str(), NULL));
return result.str();
}
std::string EncodeBDY::encode()
{
const char *days[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", "Err"};
short day = 7;
for (short i = 0; i < 7; i++)
if (strcasecmp(days[i], m_data.c_str()) == 0)
day = i;
std::ostringstream result;
result << std::setw(2) << std::hex << std::setfill('0') << day;
return result.str();
}
std::string EncodeHDY::encode()
{
const char *days[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", "Err"};
short day = 8;
for (short i = 0; i < 7; i++)
if (strcasecmp(days[i], m_data.c_str()) == 0)
day = i + 1;
std::ostringstream result;
result << std::setw(2) << std::hex << std::setfill('0') << day;
return result.str();
}
std::string EncodeTTM::encode()
{
// prepare data
std::string token;
std::istringstream stream(m_data);
std::vector<std::string> data;
while (std::getline(stream, token, ':') != 0)
data.push_back(token);
std::ostringstream result;
result << std::setw(2) << std::hex << std::setfill('0')
<< static_cast<short>( (strtod(data[0].c_str(), NULL) * 6)
+ (strtod(data[1].c_str(), NULL) / 10) );
return result.str();
}
} //namespace
+292
View File
@@ -0,0 +1,292 @@
/*
* Copyright (C) Roland Jax 2014 <roland.jax@liwest.at>
* crc calculations from http://www.mikrocontroller.net/topic/75698
*
* This file is part of libebus.
*
* libebus 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.
*
* libebus 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 libebus. If not, see http://www.gnu.org/licenses/.
*/
#ifndef LIBEBUS_ENCODE_H_
#define LIBEBUS_ENCODE_H_
#include <string>
namespace libebus
{
class Encode
{
public:
Encode(const std::string& data, const std::string& factor = "");
virtual ~Encode() {}
virtual std::string encode() = 0;
protected:
std::string m_data;
float m_factor;
};
class EncodeHEX : public Encode
{
public:
EncodeHEX(const std::string& data) : Encode(data) {}
~EncodeHEX() {}
std::string encode();
};
class EncodeUCH : public Encode
{
public:
EncodeUCH(const std::string& data, const std::string& factor)
: Encode(data, factor) {}
~EncodeUCH() {}
std::string encode();
};
class EncodeSCH : public Encode
{
public:
EncodeSCH(const std::string& data, const std::string& factor)
: Encode(data, factor) {}
~EncodeSCH() {}
std::string encode();
};
class EncodeUIN : public Encode
{
public:
EncodeUIN(const std::string& data, const std::string& factor)
: Encode(data, factor) {}
~EncodeUIN() {}
std::string encode();
};
class EncodeSIN : public Encode
{
public:
EncodeSIN(const std::string& data, const std::string& factor)
: Encode(data, factor) {}
~EncodeSIN() {}
std::string encode();
};
class EncodeULG : public Encode
{
public:
EncodeULG(const std::string& data, const std::string& factor)
: Encode(data, factor) {}
~EncodeULG() {}
std::string encode();
};
class EncodeSLG : public Encode
{
public:
EncodeSLG(const std::string& data, const std::string& factor)
: Encode(data, factor) {}
~EncodeSLG() {}
std::string encode();
};
class EncodeFLT : public Encode
{
public:
EncodeFLT(const std::string& data, const std::string& factor)
: Encode(data, factor) {}
~EncodeFLT() {}
std::string encode();
};
class EncodeSTR : public Encode
{
public:
EncodeSTR(const std::string& data) : Encode(data) {}
~EncodeSTR() {}
std::string encode();
};
class EncodeBCD : public Encode
{
public:
EncodeBCD(const std::string& data, const std::string& factor)
: Encode(data, factor) {}
~EncodeBCD() {}
std::string encode();
};
class EncodeD1B : public Encode
{
public:
EncodeD1B(const std::string& data, const std::string& factor)
: Encode(data, factor) {}
~EncodeD1B() {}
std::string encode();
};
class EncodeD1C : public Encode
{
public:
EncodeD1C(const std::string& data, const std::string& factor)
: Encode(data, factor) {}
~EncodeD1C() {}
std::string encode();
};
class EncodeD2B : public Encode
{
public:
EncodeD2B(const std::string& data, const std::string& factor)
: Encode(data, factor) {}
~EncodeD2B() {}
std::string encode();
};
class EncodeD2C : public Encode
{
public:
EncodeD2C(const std::string& data, const std::string& factor)
: Encode(data, factor) {}
~EncodeD2C() {}
std::string encode();
};
class EncodeBDA : public Encode
{
public:
EncodeBDA(const std::string& data) : Encode(data) {}
~EncodeBDA() {}
std::string encode();
};
class EncodeHDA : public Encode
{
public:
EncodeHDA(const std::string& data) : Encode(data) {}
~EncodeHDA() {}
std::string encode();
};
class EncodeBTI : public Encode
{
public:
EncodeBTI(const std::string& data) : Encode(data) {}
~EncodeBTI() {}
std::string encode();
};
class EncodeHTI : public Encode
{
public:
EncodeHTI(const std::string& data) : Encode(data) {}
~EncodeHTI() {}
std::string encode();
};
class EncodeBDY : public Encode
{
public:
EncodeBDY(const std::string& data) : Encode(data) {}
~EncodeBDY() {}
std::string encode();
};
class EncodeHDY : public Encode
{
public:
EncodeHDY(const std::string& data) : Encode(data) {}
~EncodeHDY() {}
std::string encode();
};
class EncodeTTM : public Encode
{
public:
EncodeTTM(const std::string& data) : Encode(data) {}
~EncodeTTM() {}
std::string encode();
};
} //namespace
#endif // LIBEBUS_ENCODE_H_
+264
View File
@@ -0,0 +1,264 @@
/*
* Copyright (C) Roland Jax 2014 <roland.jax@liwest.at>
*
* This file is part of libebus.
*
* libebus 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.
*
* libebus 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 libebus. If not, see http://www.gnu.org/licenses/.
*/
#include "port.h"
#include <cstdlib>
#include <cstring>
#include <termios.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
namespace libebus
{
bool Device::isOpen()
{
if (isValid() == false)
m_open = false;
return m_open;
}
bool Device::isValid()
{
if (m_noDeviceCheck == false) {
int port;
if (ioctl(m_fd, TIOCMGET, &port) == -1) {
closeDevice();
m_open = false;
return false;
}
}
return true;
}
ssize_t Device::sendBytes(const unsigned char* buffer, size_t nbytes)
{
if (isValid() == false)
return -1;
// write bytes to device
return write(m_fd, buffer, nbytes);
}
ssize_t Device::recvBytes(const long timeout, size_t maxCount)
{
if (isValid() == false)
return -1; // TODO RESULT_ERR_DEVICE
if (timeout > 0) {
fd_set readfds;
struct timeval tdiff;
// set select timeout
tdiff.tv_sec = 0;
tdiff.tv_usec = timeout;
FD_ZERO(&readfds);
FD_SET(m_fd, &readfds);
if (select(m_fd + 1, &readfds, NULL, NULL, &tdiff) != 1)
return -2; // TODO RESULT_ERR_TIMEOUT
}
ssize_t bytes_read = sizeof(m_buffer);
if (maxCount > sizeof(m_buffer))
maxCount = sizeof(m_buffer);
// read bytes from device
bytes_read = read(m_fd, m_buffer, maxCount);
for (int i = 0; i < bytes_read; i++)
m_recvBuffer.push(m_buffer[i]);
return bytes_read;
}
unsigned char Device::getByte()
{
unsigned char byte;
if (m_recvBuffer.empty() == false) {
byte = m_recvBuffer.front();
m_recvBuffer.pop();
return byte;
}
return 0;
}
void DeviceSerial::openDevice(const std::string deviceName, const bool noDeviceCheck)
{
m_noDeviceCheck = noDeviceCheck;
termios newSettings;
m_open = false;
// open file descriptor from serial device
m_fd = open(deviceName.c_str(), O_RDWR | O_NOCTTY);
if (m_fd < 0)
return;
// save current settings of serial device
tcgetattr(m_fd, &m_oldSettings);
memset(&newSettings, '\0', sizeof(newSettings));
newSettings.c_cflag |= (B2400 | CS8 | CLOCAL | CREAD);
newSettings.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
newSettings.c_iflag |= IGNPAR;
newSettings.c_oflag &= ~OPOST;
newSettings.c_cc[VMIN] = 1;
newSettings.c_cc[VTIME] = 0;
// empty device buffer
tcflush(m_fd, TCIOFLUSH);
// activate new settings of serial device
tcsetattr(m_fd, TCSANOW, &newSettings);
// set serial device into blocking mode
fcntl(m_fd, F_SETFL, fcntl(m_fd, F_GETFL) & ~O_NONBLOCK);
m_open = true;
}
void DeviceSerial::closeDevice()
{
if (m_open == true) {
// empty device buffer
tcflush(m_fd, TCIOFLUSH);
// activate old settings of serial device
tcsetattr(m_fd, TCSANOW, &m_oldSettings);
// close file descriptor from serial device
close(m_fd);
m_fd = -1;
m_open = false;
}
}
void DeviceNetwork::openDevice(const std::string deviceName, const bool noDeviceCheck)
{
m_noDeviceCheck = noDeviceCheck;
struct sockaddr_in sock;
char* hostport;
int ret;
m_open = false;
memset((char*) &sock, 0, sizeof(sock));
hostport = strdup(deviceName.c_str());
char* host = strtok(hostport, ":");
char* port = strtok(NULL, ":");
if (inet_addr(host) == INADDR_NONE) {
struct hostent* he;
he = gethostbyname(host);
if (he == NULL)
return;
memcpy(&sock.sin_addr, he->h_addr_list[0], he->h_length);
} else {
ret = inet_aton(host, &sock.sin_addr);
if (ret == 0)
return;
}
sock.sin_family = AF_INET;
sock.sin_port = htons(strtol(port, NULL, 10));
m_fd = socket(AF_INET, SOCK_STREAM, 0);
if (m_fd < 0)
return;
ret = connect(m_fd, (struct sockaddr*) &sock, sizeof(sock));
if (ret < 0)
return;
free(hostport);
m_open = true;
}
void DeviceNetwork::closeDevice()
{
if (m_open == true) {
// close file descriptor from network device
close(m_fd);
m_fd = -1;
m_open = false;
}
}
Port::Port(const std::string deviceName, const bool noDeviceCheck)
: m_deviceName(deviceName), m_noDeviceCheck(noDeviceCheck)
{
m_device = NULL;
if (strchr(deviceName.c_str(), '/') == NULL &&
strchr(deviceName.c_str(), ':') != NULL)
setType(NETWORK);
else
setType(SERIAL);
}
void Port::setType(const DeviceType type)
{
if (m_device != NULL)
delete m_device;
switch (type) {
case SERIAL:
m_device = new DeviceSerial();
break;
case NETWORK:
m_device = new DeviceNetwork();
break;
};
};
} //namespace
+122
View File
@@ -0,0 +1,122 @@
/*
* Copyright (C) Roland Jax 2014 <roland.jax@liwest.at>
*
* This file is part of libebus.
*
* libebus 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.
*
* libebus 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 libebus. If not, see http://www.gnu.org/licenses/.
*/
#ifndef LIBEBUS_PORT_H_
#define LIBEBUS_PORT_H_
#include <string>
#include <queue>
#include <termios.h>
#include <unistd.h>
namespace libebus
{
enum DeviceType { SERIAL, NETWORK };
#define MAX_READ_SIZE 100
class Device
{
public:
Device() : m_fd(-1), m_open(false), m_noDeviceCheck(false) {}
virtual ~Device() {}
virtual void openDevice(const std::string deviceName, const bool noDeviceCheck) = 0;
virtual void closeDevice() = 0;
bool isOpen();
ssize_t sendBytes(const unsigned char* buffer, size_t nbytes);
ssize_t recvBytes(const long timeout, size_t maxCount);
unsigned char getByte();
ssize_t sizeRecvBuffer() const { return m_recvBuffer.size(); }
protected:
int m_fd;
bool m_open;
bool m_noDeviceCheck;
std::queue<unsigned char> m_recvBuffer;
unsigned char m_buffer[MAX_READ_SIZE];
private:
bool isValid();
};
class DeviceSerial : public Device
{
public:
~DeviceSerial() { closeDevice(); }
void openDevice(const std::string deviceName, const bool noDeviceCheck);
void closeDevice();
private:
termios m_oldSettings;
};
class DeviceNetwork : public Device
{
public:
~DeviceNetwork() { closeDevice(); }
void openDevice(const std::string deviceName, const bool noDeviceCheck);
void closeDevice();
private:
};
class Port
{
public:
Port(const std::string deviceName, const bool noDeviceCheck);
~Port() { delete m_device; }
void open() { m_device->openDevice(m_deviceName, m_noDeviceCheck); }
void close() { m_device->closeDevice(); }
bool isOpen() { return m_device->isOpen(); }
ssize_t send(const unsigned char* buffer, size_t nbytes)
{ return m_device->sendBytes(buffer, nbytes); }
ssize_t recv(const long timeout, size_t maxCount=MAX_READ_SIZE) { return m_device->recvBytes(timeout, maxCount); }
unsigned char byte() { return m_device->getByte(); }
ssize_t size() const { return m_device->sizeRecvBuffer(); }
private:
std::string m_deviceName;
Device* m_device;
bool m_noDeviceCheck;
void setType(const DeviceType type);
};
} //namespace
#endif // LIBEBUS_PORT_H_
+43
View File
@@ -0,0 +1,43 @@
/*
* Copyright (C) John Baier 2014 <john@johnm.de>
*
* This file is part of libebus.
*
* libebus 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.
*
* libebus 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 libebus. If not, see http://www.gnu.org/licenses/.
*/
#include "result.h"
namespace libebus
{
const char* getResultCodeCStr(int resultCode) {
switch (resultCode) {
case RESULT_ERR_SEND: return "ERR_SEND: send error";
case RESULT_ERR_EXTRA_DATA: return "ERR_EXTRA_DATA: received bytes > sent bytes";
case RESULT_ERR_NAK: return "ERR_NAK: NAK received";
case RESULT_ERR_CRC: return "ERR_CRC: CRC error";
case RESULT_ERR_ACK: return "ERR_ACK: ACK error";
case RESULT_ERR_TIMEOUT: return "ERR_TIMEOUT: read timeout";
case RESULT_ERR_SYN: return "ERR_SYN: SYN received";
case RESULT_ERR_BUS_LOST: return "ERR_BUS_LOST: lost bus arbitration";
case RESULT_ERR_ESC: return "ERR_ESC: invalid escape sequence received";
case RESULT_ERR_INVALID_ARG: return "ERR_INVALID_ARG: invalid argument specified";
case RESULT_ERR_DEVICE: return "ERR_DEVICE: generic device error";
default: return "success";
}
}
} //namespace
+58
View File
@@ -0,0 +1,58 @@
/*
* Copyright (C) John Baier 2014 <john@johnm.de>
*
* This file is part of libebus.
*
* libebus 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.
*
* libebus 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 libebus. If not, see http://www.gnu.org/licenses/.
*/
#ifndef LIBEBUS_RESULT_H_
#define LIBEBUS_RESULT_H_
namespace libebus
{
static const int RESULT_OK = 0;
static const int RESULT_BUS_ACQUIRED = 1; // bus successfully acquired
static const int RESULT_DATA = 2; // some data received
static const int RESULT_SYN = 3; // regular SYN after message received
static const int RESULT_BUS_LOCKED = 4; // bus is locked for access
static const int RESULT_BUS_PRIOR_RETRY = 5; // retry to access bus
static const int RESULT_ERR_SEND = -1; // send error
static const int RESULT_ERR_EXTRA_DATA = -2; // received bytes > sent bytes
static const int RESULT_ERR_NAK = -3; // NAK received
static const int RESULT_ERR_CRC = -4; // CRC error
static const int RESULT_ERR_ACK = -5; // ACK error
static const int RESULT_ERR_TIMEOUT = -6; // read timeout
static const int RESULT_ERR_SYN = -7; // SYN received
static const int RESULT_ERR_BUS_LOST = -8; // arbitration lost
static const int RESULT_ERR_ESC = -9; // invalid escape sequence received
static const int RESULT_ERR_INVALID_ARG = -10; // invalid argument
static const int RESULT_ERR_DEVICE = -11; // generic device error (usually fatal)
/**
* @brief Return the string corresponding to the result code.
* @param resultCode the result code (see RESULT_ constants).
* @return the string corresponding to the result code.
*/
const char* getResultCodeCStr(int resultCode);
} //namespace
#endif // LIBEBUS_RESULT_H_
+176
View File
@@ -0,0 +1,176 @@
/*
* Copyright (C) John Baier 2014 <john@johnm.de>
*
* This file is part of libebus.
*
* libebus 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.
*
* libebus 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 libebus. If not, see http://www.gnu.org/licenses/.
*/
#include "symbol.h"
#include <iostream>
#include <iomanip>
namespace libebus
{
/**
* @brief CRC8 lookup table for the polynom 0x9b = x^8 + x^7 + x^4 + x^3 + x^1 + 1.
*/
static const unsigned char CRC_LOOKUP_TABLE[]
{
0x00, 0x9b, 0xad, 0x36, 0xc1, 0x5a, 0x6c, 0xf7, 0x19, 0x82, 0xb4, 0x2f, 0xd8, 0x43, 0x75, 0xee,
0x32, 0xa9, 0x9f, 0x04, 0xf3, 0x68, 0x5e, 0xc5, 0x2b, 0xb0, 0x86, 0x1d, 0xea, 0x71, 0x47, 0xdc,
0x64, 0xff, 0xc9, 0x52, 0xa5, 0x3e, 0x08, 0x93, 0x7d, 0xe6, 0xd0, 0x4b, 0xbc, 0x27, 0x11, 0x8a,
0x56, 0xcd, 0xfb, 0x60, 0x97, 0x0c, 0x3a, 0xa1, 0x4f, 0xd4, 0xe2, 0x79, 0x8e, 0x15, 0x23, 0xb8,
0xc8, 0x53, 0x65, 0xfe, 0x09, 0x92, 0xa4, 0x3f, 0xd1, 0x4a, 0x7c, 0xe7, 0x10, 0x8b, 0xbd, 0x26,
0xfa, 0x61, 0x57, 0xcc, 0x3b, 0xa0, 0x96, 0x0d, 0xe3, 0x78, 0x4e, 0xd5, 0x22, 0xb9, 0x8f, 0x14,
0xac, 0x37, 0x01, 0x9a, 0x6d, 0xf6, 0xc0, 0x5b, 0xb5, 0x2e, 0x18, 0x83, 0x74, 0xef, 0xd9, 0x42,
0x9e, 0x05, 0x33, 0xa8, 0x5f, 0xc4, 0xf2, 0x69, 0x87, 0x1c, 0x2a, 0xb1, 0x46, 0xdd, 0xeb, 0x70,
0x0b, 0x90, 0xa6, 0x3d, 0xca, 0x51, 0x67, 0xfc, 0x12, 0x89, 0xbf, 0x24, 0xd3, 0x48, 0x7e, 0xe5,
0x39, 0xa2, 0x94, 0x0f, 0xf8, 0x63, 0x55, 0xce, 0x20, 0xbb, 0x8d, 0x16, 0xe1, 0x7a, 0x4c, 0xd7,
0x6f, 0xf4, 0xc2, 0x59, 0xae, 0x35, 0x03, 0x98, 0x76, 0xed, 0xdb, 0x40, 0xb7, 0x2c, 0x1a, 0x81,
0x5d, 0xc6, 0xf0, 0x6b, 0x9c, 0x07, 0x31, 0xaa, 0x44, 0xdf, 0xe9, 0x72, 0x85, 0x1e, 0x28, 0xb3,
0xc3, 0x58, 0x6e, 0xf5, 0x02, 0x99, 0xaf, 0x34, 0xda, 0x41, 0x77, 0xec, 0x1b, 0x80, 0xb6, 0x2d,
0xf1, 0x6a, 0x5c, 0xc7, 0x30, 0xab, 0x9d, 0x06, 0xe8, 0x73, 0x45, 0xde, 0x29, 0xb2, 0x84, 0x1f,
0xa7, 0x3c, 0x0a, 0x91, 0x66, 0xfd, 0xcb, 0x50, 0xbe, 0x25, 0x13, 0x88, 0x7f, 0xe4, 0xd2, 0x49,
0x95, 0x0e, 0x38, 0xa3, 0x54, 0xcf, 0xf9, 0x62, 0x8c, 0x17, 0x21, 0xba, 0x4d, 0xd6, 0xe0, 0x7b,
};
SymbolString::SymbolString(const std::string str)
: m_crc(0)
{
// parse + escape
for (size_t i = 0; i+1 < str.size(); i += 2) {
unsigned long value = strtoul(str.substr(i, 2).c_str(), NULL, 16);
push_back_escape((unsigned char)value);
}
// add CRC + escape
push_back_escape(m_crc, false);
}
SymbolString::SymbolString(const std::string str, bool escaped)
: m_crc(0)
{
bool previousEscape = false;
// parse + optionally unescape
for (size_t i = 0; i+1 < str.size(); i += 2) {
unsigned long value = strtoul(str.substr(i, 2).c_str(), NULL, 16);
if (escaped == true) {
push_back_unescape((unsigned char)value, previousEscape, false);
}
else
m_data.push_back((unsigned char)value);
}
}
const std::string SymbolString::getDataStr(bool unescape)
{
std::stringstream sstr;
bool previousEscape = false;
for (size_t i = 0; i < size(); i++) {
unsigned char value = at(i);
if (unescape == true && previousEscape == true) {
if (value == 0x00) {
sstr << "a9"; // ESC
}
else if (value == 0x01) {
sstr << "aa"; // SYN
}
else {
sstr << "XX"; // invalid escape sequence
}
previousEscape = false;
}
else if (unescape == true && value == ESC) {
previousEscape = true; // escape sequence not yet finished
}
else {
sstr << std::nouppercase << std::setw(2) << std::hex
<< std::setfill('0') << static_cast<unsigned>(value);
}
}
return sstr.str();
}
void SymbolString::push_back_escape(const unsigned char value, bool updateCRC)
{
if (value == ESC) {
m_data.push_back(ESC);
m_data.push_back(0x00);
if (updateCRC) {
addCRC(ESC);
addCRC(0x00);
}
}
else if (value == SYN) {
m_data.push_back(ESC);
m_data.push_back(0x01);
if (updateCRC) {
addCRC(ESC);
addCRC(0x01);
}
}
else {
m_data.push_back(value);
if (updateCRC) {
addCRC(value);
}
}
}
unsigned char SymbolString::push_back_unescape(const unsigned char value, bool& previousEscape, bool updateCRC)
{
if (updateCRC) {
addCRC(value);
}
if (previousEscape == true) {
if (value == 0x00) {
m_data.push_back(ESC);
previousEscape = false;
return ESC;
}
if (value == 0x01) {
m_data.push_back(SYN);
previousEscape = false;
return SYN;
}
return 0; // invalid escape sequence
}
if (value == ESC) {
previousEscape = true;
return 1; // escape sequence not yet finished
}
m_data.push_back(value);
return value;
}
void SymbolString::addCRC(const unsigned char value) {
m_crc = CRC_LOOKUP_TABLE[m_crc]^value;
}
bool isMaster(unsigned char addr) {
unsigned char addrHi = (addr & 0xF0) >> 4;
unsigned char addrLo = (addr & 0x0F);
return ((addrHi == 0x0) || (addrHi == 0x1) || (addrHi == 0x3) || (addrHi == 0x7) || (addrHi == 0xF))
&& ((addrLo == 0x0) || (addrLo == 0x1) || (addrLo == 0x3) || (addrLo == 0x7) || (addrLo == 0xF));
}
} //namespace
+148
View File
@@ -0,0 +1,148 @@
/*
* Copyright (C) John Baier 2014 <john@johnm.de>
*
* This file is part of libebus.
*
* libebus 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.
*
* libebus 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 libebus. If not, see http://www.gnu.org/licenses/.
*/
#ifndef LIBEBUS_SYMBOL_H_
#define LIBEBUS_SYMBOL_H_
#include <cstring>
#include <cstdlib>
#include <sstream>
#include <queue>
namespace libebus
{
static const unsigned char ESC = 0xA9; // escape symbol, either followed by 0x00 for the value 0xA9, or 0x01 for the value 0xAA
static const unsigned char SYN = 0xAA; // synchronization symbol
static const unsigned char ACK = 0x00; // positive acknowledge
static const unsigned char NAK = 0xFF; // negative acknowledge
static const unsigned char BROADCAST = 0xFE; // the broadcast destination address
/**
* @brief A string of bus symbols.
*/
class SymbolString
{
public:
/**
* @brief Creates a new empty SymbolString.
*/
SymbolString() : m_crc(0) {}
/**
* @brief Creates a new escaped SymbolString from an unescaped hex string and adds the calculated CRC.
* @param str the unescaped hex string.
*/
SymbolString(const std::string str);
/**
* @brief Creates a new unescaped SymbolString from a hex string.
* @param escaped whether the hex string is escaped and shall be unescaped.
* @param str the hex string.
*/
SymbolString(const std::string str, bool escaped);
/**
* @brief Returns the symbols as hex string.
* @param escaped whether to unescape the symbols.
* @return the symbols as hex string.
*/
const std::string getDataStr(bool unescape=false);
/**
* @brief Returns the symbol at the specified index.
* @param index the index of the symbol to return.
* @return the symbol at the specified index.
* @throw std::out_of_range if @a index is invalid.
*/
unsigned char at(const size_t index) { return m_data.at(index); }
/**
* @brief Returns the symbol at the specified index.
* @param index the index of the symbol to return.
* @return the symbol at the specified index.
*/
unsigned char operator[](const size_t index) { return m_data[index]; }
/**
* @brief Returns the symbol at the specified index.
* @param index the index of the symbol to return.
* @return the symbol at the specified index.
*/
unsigned char operator[](const size_t index) const { return m_data[index]; }
/**
* @brief Inserts a the symbol at the specified index.
* @param index the index at which to insert the symbol.
* @param value the symbol to insert.
*/
void insert(const size_t index, const unsigned char value) { m_data.insert(m_data.begin()+index, value); }
/**
* @brief Appends a the symbol to the end of the symbol string and escapes it if necessary.
* @param value the symbol to append.
* @param updateCrc whether to update the calculated CRC in @a m_crc.
*/
void push_back_escape(const unsigned char value, bool updateCRC=true);
/**
* @brief Appends a the symbol to the end of the symbol string and unescapes it.
* @param value the symbol to append.
* @param previousEscape whether the previous value was the escape symbol (set to false for the initial call).
* @param updateCrc whether to update the calculated CRC in @a m_crc.
* @return if previousEscape is false on return: the unescaped symbol. otherwise: zero if the escape sequence was invalid, one if the escape sequence is not yet finished.
*/
unsigned char push_back_unescape(const unsigned char value, bool& previousEscape, bool updateCRC=true);
/**
* @brief Returns the number of symbols in this symbol string.
* @return the number of available symbols.
*/
size_t size() const { return m_data.size(); }
/**
* @brief Returns the calculated CRC.
* @return the calculated CRC.
*/
unsigned char getCRC() const { return m_crc; }
/**
* @brief Clears the symbols.
*/
void clear() { m_crc=0; m_data.clear(); }
private:
/**
* @brief Updates the calculated CRC in @a m_crc by adding a value.
* @param value the (escaped) value to add to the calculated CRC in @a m_crc.
*/
void addCRC(const unsigned char value);
/**
* @brief the string of bus symbols.
*/
std::vector<unsigned char> m_data;
/**
* @brief the calculated CRC.
*/
unsigned char m_crc;
};
/**
* Returns whether the address is one of the 25 master addresses.
* @param addr the address to check.
* @return <code>true</code> if the specified address is a master address.
*/
bool isMaster(unsigned char addr);
} //namespace
#endif // LIBEBUS_SYMBOL_H_
+37
View File
@@ -0,0 +1,37 @@
AM_CXXFLAGS = -fpic \
-Wall \
-Wextra \
-I$(top_srcdir)/src/libebus
noinst_PROGRAMS = test_port \
test_symbol \
test_bus \
test_commands \
test_configfile \
test_decode \
test_encode
test_port_SOURCES = test_port.cpp
test_port_LDADD = $(top_srcdir)/src/libebus/libebus.a
test_symbol_SOURCES = test_symbol.cpp
test_symbol_LDADD = $(top_srcdir)/src/libebus/libebus.a
test_bus_SOURCES = test_bus.cpp
test_bus_LDADD = $(top_srcdir)/src/libebus/libebus.a
test_commands_SOURCES = test_commands.cpp
test_commands_LDADD = $(top_srcdir)/src/libebus/libebus.a
test_configfile_SOURCES = test_configfile.cpp
test_configfile_LDADD = $(top_srcdir)/src/libebus/libebus.a
test_decode_SOURCES = test_decode.cpp
test_decode_LDADD = $(top_srcdir)/src/libebus/libebus.a
test_encode_SOURCES = test_encode.cpp
test_encode_LDADD = $(top_srcdir)/src/libebus/libebus.a
distclean-local:
-rm -f Makefile.in
-rm -rf .libs
+4
View File
@@ -0,0 +1,4 @@
# type;class;cmd;comment;msg type;ZZ;PBSB;NN;D1D2D3;elements;sub;part;position;datatype;factor;unit;valid;comment;sub;part;position;datatype;factor;unit;valid;comment;sub;part;position;datatype;factor;unit;valid;comment;sub;part;position;datatype;factor;unit;valid;comment
c;broad;date_time_temp;Datum, Uhrzeit und Aussentempertur;BR;FE;0700;9;-;4;temp;md;1,2;d2b;1.0;°C;-;Temperatur;day;md;8;bdy;-;-;-;Wochentag;date;md;6,7,9;bda;-;-;-;Datum;time;md;5,4,3;bti;-;-;-;Uhrzeit
g;ci;Password;Kennwort;MS;15;B509;3;0D2C00;4;pin1;sd;1;uch;-;-;-;Pin 1;pin2;sd;2;uch;-;-;-;Pin 2;pin3;sd;3;uch;-;-;-;Pin 3;pin4;sd;4;uch;-;-;-;Pin 4
s;vwxmk;DesiredTemp;Solltemperatur;MS;50;B509;4;0E3200;1;-;sd;1;d1c;1.0;°C;-;-;;;;;;;;;;;;;;;;;;;;;;;;
1 # type class cmd comment msg type ZZ PBSB NN D1D2D3 elements sub part position datatype factor unit valid comment sub part position datatype factor unit valid comment sub part position datatype factor unit valid comment sub part position datatype factor unit valid comment
2 c broad date_time_temp Datum, Uhrzeit und Aussentempertur BR FE 0700 9 - 4 temp md 1,2 d2b 1.0 °C - Temperatur day md 8 bdy - - - Wochentag date md 6,7,9 bda - - - Datum time md 5,4,3 bti - - - Uhrzeit
3 g ci Password Kennwort MS 15 B509 3 0D2C00 4 pin1 sd 1 uch - - - Pin 1 pin2 sd 2 uch - - - Pin 2 pin3 sd 3 uch - - - Pin 3 pin4 sd 4 uch - - - Pin 4
4 s vwxmk DesiredTemp Solltemperatur MS 50 B509 4 0E3200 1 - sd 1 d1c 1.0 °C - -
+58
View File
@@ -0,0 +1,58 @@
/*
* Copyright (C) Roland Jax 2014 <roland.jax@liwest.at>
*
* This file is part of libebus.
*
* libebus 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.
*
* libebus 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 libebus. If not, see http://www.gnu.org/licenses/.
*/
#include "bus.h"
#include <iostream>
#include <iomanip>
using namespace libebus;
int main ()
{
Bus bus("/dev/ttyUSB0", true, 15000, "/tmp/dump_bus.bin", 100, false);
bus.connect();
if (bus.isConnected() == true)
std::cout << "connect successful." << std::endl;
int cout = 0;
while (cout++ < 1000) {
if (bus.isConnected() == true) {
bus.printBytes();
} else {
sleep(5);
bus.connect();
if (bus.isConnected() == false)
std::cout << "can't open /dev/ttyUSB0" << std::endl;
else
std::cout << "reconnect successful." << std::endl;
}
}
bus.disconnect();
if (bus.isConnected() == false)
std::cout << "disconnect successful." << std::endl;
return 0;
}
+86
View File
@@ -0,0 +1,86 @@
/*
* Copyright (C) Roland Jax 2014 <roland.jax@liwest.at>
*
* This file is part of libebus.
*
* libebus 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.
*
* libebus 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 libebus. If not, see http://www.gnu.org/licenses/.
*/
#include "configfile.h"
#include "commands.h"
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <vector>
using namespace libebus;
// will be part of cfg csv class
void readCSV(std::istream& is, Commands& commands){
std::string line;
// read lines
while (std::getline(is, line) != 0) {
std::vector<std::string> row;
std::string column;
int count;
count = 0;
std::istringstream stream(line);
// walk through columns
while (std::getline(stream, column, ';') != 0) {
row.push_back(column);
count++;
}
commands.addCommand(row);
}
}
int main()
{
Commands* commands = ConfigCommands("test", CSV).getCommands();
std::cout << "Commands: " << commands->sizeCmdDB() << std::endl;
//~ std::string data("g ci password pin1");
std::string data("s vwxmk DesiredTemp");
int index = commands->findCommand(data);
std::cout << "found at index: " << index << std::endl;
// prepare data
std::string token;
std::istringstream stream(data);
std::vector<std::string> cmd;
// split stream
while (std::getline(stream, token, ' ') != 0)
cmd.push_back(token);
//~ Command* command = new Command(index, (*commands)[index], "ff15b509030d2c0035000401000000cf00");
Command* command = new Command(index, (*commands)[index], "19.0");
//~ std::string result = command->calcResult(cmd);
std::string result = command->calcData();
std::cout << "result: " << result << std::endl;
delete command;
return 0;
}
+48
View File
@@ -0,0 +1,48 @@
/*
* Copyright (C) Roland Jax 2014 <roland.jax@liwest.at>
*
* This file is part of libebus.
*
* libebus 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.
*
* libebus 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 libebus. If not, see http://www.gnu.org/licenses/.
*/
#include "configfile.h"
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <vector>
using namespace libebus;
int main() {
std::string dir("test");
ConfigCommands config(dir, CSV);
Commands* commands = config.getCommands();
std::cout << "size: " << commands->sizeCmdDB() << std::endl;
commands->findCommand("g ci Password");
std::cout << (*commands)[0][0] << std::endl;
delete commands;
return 0;
}
+310
View File
@@ -0,0 +1,310 @@
/*
* Copyright (C) Roland Jax 2014 <roland.jax@liwest.at>
*
* This file is part of libebus.
*
* libebus 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.
*
* libebus 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 libebus. If not, see http://www.gnu.org/licenses/.
*/
#include "decode.h"
#include <iostream>
#include <iomanip>
using namespace libebus;
int main()
{
Decode* help_dec = NULL;
std::cout << std::endl;
// HEX
{
const char* hex[] = {"53706569636865722020"};
for (size_t i = 0; i < sizeof(hex)/sizeof(hex[0]); i++) {
help_dec = new DecodeHEX(hex[i]);
std::cout << "DecodeHEX: " << std::setw(20) << hex[i] << " = " << help_dec->decode() << std::endl;
delete help_dec;
}
std::cout << std::endl;
}
// UCH
{
const char* uch[] = {"00", "01", "7f", "80", "fe", "ff", "a1"};
for (size_t i = 0; i < sizeof(uch)/sizeof(uch[0]); i++) {
help_dec = new DecodeUCH(uch[i], "1.0");
std::cout << "DecodeUCH: " << std::setw(20) << uch[i] << " = " << help_dec->decode() << std::endl;
delete help_dec;
}
std::cout << std::endl;
}
// SCH
{
const char* sch[] = {"00", "01", "7f", "80", "fe", "ff", "a1"};
for (size_t i = 0; i < sizeof(sch)/sizeof(sch[0]); i++) {
help_dec = new DecodeSCH(sch[i], "1.0");
std::cout << "DecodeSCH: " << std::setw(20) << sch[i] << " = " << help_dec->decode() << std::endl;
delete help_dec;
}
std::cout << std::endl;
}
// UIN
{
const char* uin[] = {"0000", "0001", "7fff", "8000", "fffe", "ffff", "a1b2"};
for (size_t i = 0; i < sizeof(uin)/sizeof(uin[0]); i++) {
help_dec = new DecodeUIN(uin[i], "1.0");
std::cout << "DecodeUIN: " << std::setw(20) << uin[i] << " = " << help_dec->decode() << std::endl;
delete help_dec;
}
std::cout << std::endl;
}
// SIN
{
const char* sin[] = {"0000", "0001", "7fff", "8000", "fffe", "ffff", "a1b2"};
for (size_t i = 0; i < sizeof(sin)/sizeof(sin[0]); i++) {
help_dec = new DecodeSIN(sin[i], "1.0");
std::cout << "DecodeSIN: " << std::setw(20) << sin[i] << " = " << help_dec->decode() << std::endl;
delete help_dec;
}
std::cout << std::endl;
}
// ULG
{
const char* ulg[] = {"00000000", "00000001", "7fffffff", "80000000", "fffffffe", "ffffffff", "a1b2c3d4"};
for (size_t i = 0; i < sizeof(ulg)/sizeof(ulg[0]); i++) {
help_dec = new DecodeULG(ulg[i], "1.0");
std::cout << "DecodeULG: " << std::setw(20) << ulg[i] << " = " << help_dec->decode() << std::endl;
delete help_dec;
}
std::cout << std::endl;
}
// SLG
{
const char* slg[] = {"00000000", "00000001", "7fffffff", "80000000", "fffffffe", "ffffffff", "a1b2c3d4"};
for (size_t i = 0; i < sizeof(slg)/sizeof(slg[0]); i++) {
help_dec = new DecodeSLG(slg[i], "1.0");
std::cout << "DecodeSLG: " << std::setw(20) << slg[i] << " = " << help_dec->decode() << std::endl;
delete help_dec;
}
std::cout << std::endl;
}
// FLT
{
const char* flt[] = {"0000", "081b", "2532", "2689", "0851"};
for (size_t i = 0; i < sizeof(flt)/sizeof(flt[0]); i++) {
help_dec = new DecodeFLT(flt[i], "1.0");
std::cout << "DecodeFLT: " << std::setw(20) << flt[i] << " = " << help_dec->decode() << std::endl;
delete help_dec;
}
std::cout << std::endl;
}
// STR
{
const char* str[] = {"53706569636865722020", "5644363030" };
for (size_t i = 0; i < sizeof(str)/sizeof(str[0]); i++) {
help_dec = new DecodeSTR(str[i]);
std::cout << "DecodeSTR: " << std::setw(20) << str[i] << " = " << help_dec->decode() << std::endl;
delete help_dec;
}
std::cout << std::endl;
}
// BCD
{
const char* bcd[] = {"00", "01", "02", "03", "12", "99"};
for (size_t i = 0; i < sizeof(bcd)/sizeof(bcd[0]); i++) {
help_dec = new DecodeBCD(bcd[i], "1.0");
std::cout << "DecodeBCD: " << std::setw(20) << bcd[i] << " = " << help_dec->decode() << std::endl;
delete help_dec;
}
std::cout << std::endl;
}
// D1B
{
const char* d1b[] = {"00", "01", "7f", "81", "80"};
for (size_t i = 0; i < sizeof(d1b)/sizeof(d1b[0]); i++) {
help_dec = new DecodeD1B(d1b[i], "1.0");
std::cout << "DecodeD1B: " << std::setw(20) << d1b[i] << " = " << help_dec->decode() << std::endl;
delete help_dec;
}
std::cout << std::endl;
}
// D1C
{
const char* d1c[] = {"00", "64", "c8"};
for (size_t i = 0; i < sizeof(d1c)/sizeof(d1c[0]); i++) {
help_dec = new DecodeD1C(d1c[i], "1.0");
std::cout << "DecodeD1C: " << std::setw(20) << d1c[i] << " = " << help_dec->decode() << std::endl;
delete help_dec;
}
std::cout << std::endl;
}
// D2B
{
const char* d2b[] = {"0000", "0100", "ffff", "00ff", "0080", "0180", "ff7f"};
for (size_t i = 0; i < sizeof(d2b)/sizeof(d2b[0]); i++) {
help_dec = new DecodeD2B(d2b[i], "1.0");
std::cout << "DecodeD2B: " << std::setw(20) << d2b[i] << " = " << help_dec->decode() << std::endl;
delete help_dec;
}
std::cout << std::endl;
}
// D2C
{
const char* d2c[] = {"0000", "0100", "ffff", "f0ff", "0080", "0180", "ff7f"};
for (size_t i = 0; i < sizeof(d2c)/sizeof(d2c[0]); i++) {
help_dec = new DecodeD2C(d2c[i], "1.0");
std::cout << "DecodeD2C: " << std::setw(20) << d2c[i] << " = " << help_dec->decode() << std::endl;
delete help_dec;
}
std::cout << std::endl;
}
// BDA
{
const char* bda[] = {"171113", "220901"};
for (size_t i = 0; i < sizeof(bda)/sizeof(bda[0]); i++) {
help_dec = new DecodeBDA(bda[i]);
std::cout << "DecodeBDA: " << std::setw(20) << bda[i] << " = " << help_dec->decode() << std::endl;
delete help_dec;
}
std::cout << std::endl;
}
// HDA
{
const char* hda[] = {"010101", "1f0c1b"};
for (size_t i = 0; i < sizeof(hda)/sizeof(hda[0]); i++) {
help_dec = new DecodeHDA(hda[i]);
std::cout << "DecodeHDA: " << std::setw(20) << hda[i] << " = " << help_dec->decode() << std::endl;
delete help_dec;
}
std::cout << std::endl;
}
// BTI
{
const char* bti[] = {"010101", "174209", "235959"};
for (size_t i = 0; i < sizeof(bti)/sizeof(bti[0]); i++) {
help_dec = new DecodeBTI(bti[i]);
std::cout << "DecodeBTI: " << std::setw(20) << bti[i] << " = " << help_dec->decode() << std::endl;
delete help_dec;
}
std::cout << std::endl;
}
// HTI
{
const char* hti[] = {"010101", "112a09", "173b3b"};
for (size_t i = 0; i < sizeof(hti)/sizeof(hti[0]); i++) {
help_dec = new DecodeHTI(hti[i]);
std::cout << "DecodeHTI: " << std::setw(20) << hti[i] << " = " << help_dec->decode() << std::endl;
delete help_dec;
}
std::cout << std::endl;
}
// BDY
{
const char* bdy[] = {"01", "03", "06", "07"};
for (size_t i = 0; i < sizeof(bdy)/sizeof(bdy[0]); i++) {
help_dec = new DecodeBDY(bdy[i]);
std::cout << "DecodeBDY: " << std::setw(20) << bdy[i] << " = " << help_dec->decode() << std::endl;
delete help_dec;
}
std::cout << std::endl;
}
// HDY
{
const char* hdy[] = {"01", "03", "07", "08"};
for (size_t i = 0; i < sizeof(hdy)/sizeof(hdy[0]); i++) {
help_dec = new DecodeHDY(hdy[i]);
std::cout << "DecodeHDY: " << std::setw(20) << hdy[i] << " = " << help_dec->decode() << std::endl;
delete help_dec;
}
std::cout << std::endl;
}
// TTM
{
const char* ttm[] = {"00", "23", "4f", "90"};
for (size_t i = 0; i < sizeof(ttm)/sizeof(ttm[0]); i++) {
help_dec = new DecodeTTM(ttm[i]);
std::cout << "DecodeTTM: " << std::setw(20) << ttm[i] << " = " << help_dec->decode() << std::endl;
delete help_dec;
}
std::cout << std::endl;
}
return 0;
}
+311
View File
@@ -0,0 +1,311 @@
/*
* Copyright (C) Roland Jax 2014 <roland.jax@liwest.at>
*
* This file is part of libebus.
*
* libebus 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.
*
* libebus 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 libebus. If not, see http://www.gnu.org/licenses/.
*/
#include "encode.h"
#include <iostream>
#include <iomanip>
using namespace libebus;
int main()
{
Encode* help_enc = NULL;
std::cout << std::endl;
// HEX
{
const char* hex[] = {"53 70 65 69 63 68 65 72 20 20"};
for (size_t i = 0; i < sizeof(hex)/sizeof(hex[0]); i++) {
help_enc = new EncodeHEX(hex[i]);
std::cout << "EncodeHEX: " << std::setw(20) << hex[i] << " = " << help_enc->encode() << std::endl;
delete help_enc;
}
std::cout << std::endl;
}
// UCH
{
const char* uch[] = {"0", "1", "127", "128", "254", "255", "161"};
for (size_t i = 0; i < sizeof(uch)/sizeof(uch[0]); i++) {
help_enc = new EncodeUCH(uch[i], "1.0");
std::cout << "EncodeUCH: " << std::setw(20) << uch[i] << " = " << help_enc->encode() << std::endl;
delete help_enc;
}
std::cout << std::endl;
}
// SCH
{
const char* sch[] = {"0", "1", "127", "-128", "-2", "-1", "-95"};
for (size_t i = 0; i < sizeof(sch)/sizeof(sch[0]); i++) {
help_enc = new EncodeSCH(sch[i], "1.0");
std::cout << "EncodeSCH: " << std::setw(20) << sch[i] << " = " << help_enc->encode() << std::endl;
delete help_enc;
}
std::cout << std::endl;
}
// UIN
{
const char* uin[] = {"0", "1", "32767", "32768", "65534", "65535", "41394"};
for (size_t i = 0; i < sizeof(uin)/sizeof(uin[0]); i++) {
help_enc = new EncodeUIN(uin[i], "1.0");
std::cout << "EncodeUIN: " << std::setw(20) << uin[i] << " = " << help_enc->encode() << std::endl;
delete help_enc;
}
std::cout << std::endl;
}
// SIN
{
const char* sin[] = {"0", "1", "32767", "-32768", "-2", "-1", "-24142"};
for (size_t i = 0; i < sizeof(sin)/sizeof(sin[0]); i++) {
help_enc = new EncodeSIN(sin[i], "1.0");
std::cout << "EncodeSIN: " << std::setw(20) << sin[i] << " = " << help_enc->encode() << std::endl;
delete help_enc;
}
std::cout << std::endl;
}
// ULG
{
const char* ulg[] = {"0", "1", "2147483647", "2147483648", "4294967294", "4294967295", "2712847316"};
for (size_t i = 0; i < sizeof(ulg)/sizeof(ulg[0]); i++) {
help_enc = new EncodeULG(ulg[i], "1.0");
std::cout << "EncodeULG: " << std::setw(20) << ulg[i] << " = " << help_enc->encode() << std::endl;
delete help_enc;
}
std::cout << std::endl;
}
// SLG
{
const char* slg[] = {"0", "1", "2147483647", "-2147483648", "-2", "-1", "-1582119980"};
for (size_t i = 0; i < sizeof(slg)/sizeof(slg[0]); i++) {
help_enc = new EncodeSLG(slg[i], "1.0");
std::cout << "EncodeSLG: " << std::setw(20) << slg[i] << " = " << help_enc->encode() << std::endl;
delete help_enc;
}
std::cout << std::endl;
}
// FLT
{
const char* flt[] = {"0.000", "2.075", "9.522", "9.865", "2.129"};
for (size_t i = 0; i < sizeof(flt)/sizeof(flt[0]); i++) {
help_enc = new EncodeFLT(flt[i], "1.0");
std::cout << "EncodeFLT: " << std::setw(20) << flt[i] << " = " << help_enc->encode() << std::endl;
delete help_enc;
}
std::cout << std::endl;
}
// STR
{
const char* str[] = {"Speicher ", "VD600" };
for (size_t i = 0; i < sizeof(str)/sizeof(str[0]); i++) {
help_enc = new EncodeSTR(str[i]);
std::cout << "EncodeSTR: " << std::setw(20) << str[i] << " = " << help_enc->encode() << std::endl;
delete help_enc;
}
std::cout << std::endl;
}
// BCD
{
const char* bcd[] = {"0", "1", "2", "3", "12", "99"};
for (size_t i = 0; i < sizeof(bcd)/sizeof(bcd[0]); i++) {
help_enc = new EncodeBCD(bcd[i], "1.0");
std::cout << "EncodeBCD: " << std::setw(20) << bcd[i] << " = " << help_enc->encode() << std::endl;
delete help_enc;
}
std::cout << std::endl;
}
// D1B
{
const char* d1b[] = {"00", "01", "127", "-127", "-128"};
for (size_t i = 0; i < sizeof(d1b)/sizeof(d1b[0]); i++) {
help_enc = new EncodeD1B(d1b[i], "1.0");
std::cout << "EncodeD1B: " << std::setw(20) << d1b[i] << " = " << help_enc->encode() << std::endl;
delete help_enc;
}
std::cout << std::endl;
}
// D1C
{
const char* d1c[] = {"0", "50", "100"};
for (size_t i = 0; i < sizeof(d1c)/sizeof(d1c[0]); i++) {
help_enc = new EncodeD1C(d1c[i], "1.0");
std::cout << "EncodeD1C: " << std::setw(20) << d1c[i] << " = " << help_enc->encode() << std::endl;
delete help_enc;
}
std::cout << std::endl;
}
// D2B
{
const char* d2b[] = {"0", "0.00390625", "-0.00390625", "-1", "-128", "-127.99609375", "127.99609375"};
for (size_t i = 0; i < sizeof(d2b)/sizeof(d2b[0]); i++) {
help_enc = new EncodeD2B(d2b[i], "1.0");
std::cout << "EncodeD2B: " << std::setw(20) << d2b[i] << " = " << help_enc->encode() << std::endl;
delete help_enc;
}
std::cout << std::endl;
}
// D2C
{
const char* d2c[] = {"0", "0.0625", "-0.0625", "-1", "-2048", "-2047.9375", "2047.9375"};
for (size_t i = 0; i < sizeof(d2c)/sizeof(d2c[0]); i++) {
help_enc = new EncodeD2C(d2c[i], "1.0");
std::cout << "EncodeD2C: " << std::setw(20) << d2c[i] << " = " << help_enc->encode() << std::endl;
delete help_enc;
}
std::cout << std::endl;
}
// BDA
{
const char* bda[] = {"17.11.2013", "22.09.2001"};
for (size_t i = 0; i < sizeof(bda)/sizeof(bda[0]); i++) {
help_enc = new EncodeBDA(bda[i]);
std::cout << "EncodeBDA: " << std::setw(20) << bda[i] << " = " << help_enc->encode() << std::endl;
delete help_enc;
}
std::cout << std::endl;
}
// HDA
{
const char* hda[] = {"01.01.2001", "31.12.2027"};
for (size_t i = 0; i < sizeof(hda)/sizeof(hda[0]); i++) {
help_enc = new EncodeHDA(hda[i]);
std::cout << "EncodeHDA: " << std::setw(20) << hda[i] << " = " << help_enc->encode() << std::endl;
delete help_enc;
}
std::cout << std::endl;
}
// BTI
{
const char* bti[] = {"01:01:01", "17:42:09", "23:59:59"};
for (size_t i = 0; i < sizeof(bti)/sizeof(bti[0]); i++) {
help_enc = new EncodeBTI(bti[i]);
std::cout << "EncodeBTI: " << std::setw(20) << bti[i] << " = " << help_enc->encode() << std::endl;
delete help_enc;
}
std::cout << std::endl;
}
// HTI
{
const char* hti[] = {"01:01:01", "17:42:09", "23:59:59"};
for (size_t i = 0; i < sizeof(hti)/sizeof(hti[0]); i++) {
help_enc = new EncodeHTI(hti[i]);
std::cout << "EncodeHTI: " << std::setw(20) << hti[i] << " = " << help_enc->encode() << std::endl;
delete help_enc;
}
std::cout << std::endl;
}
// BDY
{
const char* bdy[] = {"Tue", "Thu", "Sun", "Err"};
for (size_t i = 0; i < sizeof(bdy)/sizeof(bdy[0]); i++) {
help_enc = new EncodeBDY(bdy[i]);
std::cout << "EncodeBDY: " << std::setw(20) << bdy[i] << " = " << help_enc->encode() << std::endl;
delete help_enc;
}
std::cout << std::endl;
}
// HDY
{
const char* hdy[] = {"Mon", "Wed", "Sun", "Err"};
for (size_t i = 0; i < sizeof(hdy)/sizeof(hdy[0]); i++) {
help_enc = new EncodeHDY(hdy[i]);
std::cout << "EncodeHDY: " << std::setw(20) << hdy[i] << " = " << help_enc->encode() << std::endl;
delete help_enc;
}
std::cout << std::endl;
}
// TTM
{
const char* ttm[] = {"00:00", "05:50", "13:10", "24:00"};
for (size_t i = 0; i < sizeof(ttm)/sizeof(ttm[0]); i++) {
help_enc = new EncodeTTM(ttm[i]);
std::cout << "EncodeTTM: " << std::setw(20) << ttm[i] << " = " << help_enc->encode() << std::endl;
delete help_enc;
}
std::cout << std::endl;
}
return 0;
}
+60
View File
@@ -0,0 +1,60 @@
/*
* Copyright (C) Roland Jax 2014 <roland.jax@liwest.at>
*
* This file is part of libebus.
*
* libebus 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.
*
* libebus 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 libebus. If not, see http://www.gnu.org/licenses/.
*/
#include "port.h"
#include <iostream>
#include <iomanip>
using namespace libebus;
int main ()
{
std::string dev("/dev/ttyUSB20");
Port port(dev, true);
port.open();
if(port.isOpen() == true)
std::cout << "openPort successful." << std::endl;
int count = 0;
while (1) {
ssize_t bytes_read;
unsigned char byte = 0;
bytes_read = port.recv(0);
for (int i = 0; i < bytes_read; i++)
byte = port.byte();
std::cout << std::hex << std::setw(2) << std::setfill('0')
<< static_cast<unsigned>(byte) << std::endl;
bytes_read = 0;
count++;
}
port.close();
if(port.isOpen() == false)
std::cout << "closePort successful." << std::endl;
return 0;
}
+75
View File
@@ -0,0 +1,75 @@
/*
* Copyright (C) John Baier 2014 <john@johnm.de>
*
* This file is part of libebus.
*
* libebus 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.
*
* libebus 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 libebus. If not, see http://www.gnu.org/licenses/.
*/
#include "symbol.h"
#include <iostream>
#include <iomanip>
using namespace libebus;
int main ()
{
SymbolString sstr("10feb5050427a915aa");
std::stringstream out;
for (size_t i = 0; i<sstr.size(); i++) {
out << std::nouppercase << std::setw(2) << std::hex
<< std::setfill('0') << static_cast<unsigned>(sstr[i]);
}
std::string gotStr = out.str(), expectStr = "10feb5050427a90015a90177";
if (strcasecmp(gotStr.c_str(), expectStr.c_str()) == 0)
std::cout << "ctor escaped successful." << std::endl;
else
std::cout << "ctor escaped invalid: got " << gotStr
<< ", expected " << expectStr << std::endl;
unsigned char gotCrc = sstr.getCRC(), expectCrc = 0x77;
if (gotCrc == expectCrc)
std::cout << "CRC successful." << std::endl;
else
std::cout << "CRC invalid: got 0x"
<< std::nouppercase << std::setw(2) << std::hex
<< std::setfill('0') << static_cast<unsigned>(gotCrc)
<< ", expected 0x"
<< std::nouppercase << std::setw(2) << std::hex
<< std::setfill('0') << static_cast<unsigned>(expectCrc)
<< std::endl;
gotStr = sstr.getDataStr(true), expectStr = "10feb5050427a915aa77";
if (strcasecmp(gotStr.c_str(), expectStr.c_str()) == 0)
std::cout << "unescape successful." << std::endl;
else
std::cout << "unescape invalid: got " << gotStr
<< ", expected " << expectStr << std::endl;
sstr = SymbolString("10feb5050427a90015a90177", true);
gotStr = sstr.getDataStr(false);
if (strcasecmp(gotStr.c_str(), expectStr.c_str()) == 0)
std::cout << "ctor unescaped successful." << std::endl;
else
std::cout << "ctor unescaped invalid: got " << gotStr
<< ", expected " << expectStr << std::endl;
return 0;
}
+17
View File
@@ -0,0 +1,17 @@
AM_CXXFLAGS = -fpic \
-Wall \
-Wextra \
-I$(top_srcdir)/src/libcore \
-I$(top_srcdir)/src/libebus
bin_PROGRAMS = ebusctl
ebusctl_SOURCES = ebusctl.cpp
ebusctl_LDADD = $(top_srcdir)/src/libcore/libcore.a \
$(top_srcdir)/src/libebus/libebus.a
distclean-local:
-rm -f Makefile.in
-rm -rf .libs
+2 -1
View File
@@ -17,7 +17,8 @@
* along with ebusd. If not, see http://www.gnu.org/licenses/.
*/
#include "libebus.h"
#include "port.h"
#include "decode.h"
#include "appl.h"
#include "tcpsocket.h"
#include <iostream>