first working version

This commit is contained in:
Thomas Kunze 2018-03-20 22:04:11 +01:00
parent 649d831f7f
commit 7a30d482a5
13 changed files with 79 additions and 176 deletions

View File

@ -28,7 +28,7 @@ uint16_t AddressTableObject::entryCount()
if (loadState() != LS_LOADED) if (loadState() != LS_LOADED)
return 0; return 0;
return _groupAddresses[0]; return ntohs(_groupAddresses[0]);
} }
uint16_t AddressTableObject::getGa(uint16_t tsap) uint16_t AddressTableObject::getGa(uint16_t tsap)
@ -36,14 +36,14 @@ uint16_t AddressTableObject::getGa(uint16_t tsap)
if (loadState() != LS_LOADED || tsap > entryCount() ) if (loadState() != LS_LOADED || tsap > entryCount() )
return 0; return 0;
return _groupAddresses[tsap]; return ntohs(_groupAddresses[tsap]);
} }
uint16_t AddressTableObject::getTsap(uint16_t addr) uint16_t AddressTableObject::getTsap(uint16_t addr)
{ {
uint16_t size = entryCount(); uint16_t size = entryCount();
for (uint16_t i = 1; i <= size; i++) for (uint16_t i = 1; i <= size; i++)
if (_groupAddresses[i] == addr) if (ntohs(_groupAddresses[i]) == addr)
return i; return i;
return 1; return 1;
} }
@ -70,7 +70,7 @@ bool AddressTableObject::contains(uint16_t addr)
{ {
uint16_t size = entryCount(); uint16_t size = entryCount();
for (uint16_t i = 1; i <= size; i++) for (uint16_t i = 1; i <= size; i++)
if (_groupAddresses[i] == addr) if (ntohs(_groupAddresses[i]) == addr)
return true; return true;
return false; return false;
@ -82,9 +82,4 @@ void AddressTableObject::beforeStateChange(LoadState& newState)
return; return;
_groupAddresses = (uint16_t*)_data; _groupAddresses = (uint16_t*)_data;
uint16_t count = reverseByteOrder(_groupAddresses[0]);
// big endian -> little endian
for (size_t i = 0; i <= count; i++)
_groupAddresses[i] = reverseByteOrder(_groupAddresses[i]);
} }

View File

@ -9,6 +9,7 @@ APDU::APDU(uint8_t* data, CemiFrame& frame): _data(data), _frame(frame)
ApduType APDU::type() ApduType APDU::type()
{ {
uint16_t apci; uint16_t apci;
apci = getWord(_data);
popWord(apci, _data); popWord(apci, _data);
apci &= 0x3ff; apci &= 0x3ff;
if ((apci >> 6) < 11) //short apci if ((apci >> 6) < 11) //short apci
@ -18,6 +19,7 @@ ApduType APDU::type()
void APDU::type(ApduType atype) void APDU::type(ApduType atype)
{ {
// ApduType is in big endian so convert to host first, pushWord converts back
pushWord((uint16_t)atype, _data); pushWord((uint16_t)atype, _data);
} }

View File

@ -43,7 +43,10 @@ uint8_t ApplicationProgramObject::propertySize(PropertyID id)
{ {
switch (id) switch (id)
{ {
case PID_PROG_VERSION: case PID_OBJECT_TYPE:
case PID_PEI_TYPE:
return 1;
case PID_PROG_VERSION:
return 5; return 5;
} }
return TableObject::propertySize(id); return TableObject::propertySize(id);

View File

@ -25,7 +25,7 @@ void AssociationTableObject::readProperty(PropertyID id, uint32_t start, uint32_
uint16_t AssociationTableObject::entryCount() uint16_t AssociationTableObject::entryCount()
{ {
return _tableData[0]; return ntohs(_tableData[0]);
} }
uint16_t AssociationTableObject::operator[](uint16_t idx) uint16_t AssociationTableObject::operator[](uint16_t idx)
@ -33,7 +33,7 @@ uint16_t AssociationTableObject::operator[](uint16_t idx)
if (idx < 0 || idx >= entryCount()) if (idx < 0 || idx >= entryCount())
return 0; return 0;
return _tableData[idx + 1]; return ntohs(_tableData[idx + 1]);
} }
uint8_t* AssociationTableObject::save(uint8_t* buffer) uint8_t* AssociationTableObject::save(uint8_t* buffer)
@ -53,7 +53,7 @@ int32_t AssociationTableObject::translateAsap(uint16_t asap)
uint16_t entries = entryCount(); uint16_t entries = entryCount();
for (uint16_t i = 0; i < entries; i++) for (uint16_t i = 0; i < entries; i++)
{ {
uint16_t entry = operator[](i); uint16_t entry = ntohs(operator[](i));
if (lowByte(entry) == asap) if (lowByte(entry) == asap)
return highByte(entry); return highByte(entry);
} }
@ -66,9 +66,4 @@ void AssociationTableObject::beforeStateChange(LoadState& newState)
return; return;
_tableData = (uint16_t*)_data; _tableData = (uint16_t*)_data;
uint16_t count = reverseByteOrder(_tableData[0]);
// big endian -> little endian
for (size_t i = 0; i <= count; i++)
_tableData[i] = reverseByteOrder(_tableData[i]);
} }

View File

@ -50,7 +50,7 @@ uint8_t* pushInt(uint32_t i, uint8_t* data)
data[0] = ((i >> 24) & 0xff); data[0] = ((i >> 24) & 0xff);
data[1] = ((i >> 16) & 0xff); data[1] = ((i >> 16) & 0xff);
data[2] = ((i >> 8) & 0xff); data[2] = ((i >> 8) & 0xff);
data[3] = (i & 0xff); data[3] = (i & 0xff);
data += 4; data += 4;
return data; return data;
} }
@ -66,10 +66,10 @@ uint8_t* pushByteArray(const uint8_t* src, uint32_t size, uint8_t* data)
uint16_t getWord(uint8_t* data) uint16_t getWord(uint8_t* data)
{ {
return (data[0] << 8) + data[1];; return (data[0] << 8) + data[1];
} }
uint32_t getInt(uint8_t * data) uint32_t getInt(uint8_t * data)
{ {
return (data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3];; return (data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3];
} }

124
bits.h
View File

@ -1,125 +1,19 @@
/*
* bits.h - Bit and uint8_t manipulation functions.
*
* Copyright (c) 2014 Stefan Taferner <stefan.taferner@gmx.at>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*/
#pragma once #pragma once
#include <stdint.h> #include <stdint.h>
/**
* Compute the value of the specified bit.
*
* @param bitno - the number of the bit (0, 1, 2... 31)
*/
#define bit(bitno) (1UL << (bitno))
/** #ifdef __linux__
* Clear the bit of a number. The number can be #include <arpa/inet.h>
* any integer (uint8_t, short, uint32_t, long).
*
* @param val - the number from which to clear the bit
* @param bitno - the number of the bit (0, 1, 2... 31)
*/
#define bitClear(val, bitno) ((val) &= ~(1UL << (bitno)))
/**
* Set the bit of a number. The number can be
* any integer (uint8_t, short, uint32_t, long).
*
* @param val - the number from which to set the bit
* @param bitno - the number of the bit (0, 1, 2... 31)
*/
#define bitSet(val, bitno) ((val) |= 1UL << (bitno))
/**
* Write the value of a bit of a number.
*
* @param val - the number from which to write the bit
* @param bitno - the number of the bit (0, 1, 2... 31)
* @param b - the bit value (0 or 1)
*/
#define bitWrite(val, bitno, b) ((b) ? bitSet(val, bitno) : bitClear(val, bitno))
/**
* Read the value of a bit of a number. The number can be
* any integer (uint8_t, short, uint32_t, long).
*
* @param val - the number from which to get the bit
* @param bitno - the number of the bit (0, 1, 2... 31)
* @return The value of the bit (0 or 1).
*/
#define bitRead(val, bitno) (((val) >> (bitno)) & 1)
/**
* Extract the lowest (rightmost) uint8_t of a number. The number can be
* any integer (uint8_t, short, uint32_t, long).
*
* @param val - the value to extract the lowest uint8_t.
* @return The extracted uint8_t (0..255)
*/
#define lowByte(val) ((val) & 255) #define lowByte(val) ((val) & 255)
/**
* Extract the highest (leftmost) uint8_t of a number. The number can be
* any integer (uint8_t, short, uint32_t, long).
*
* @param val - the value to extract the highest uint8_t.
* @return The extracted uint8_t (0..255)
*/
#define highByte(val) (((val) >> ((sizeof(val) - 1) << 3)) & 255) #define highByte(val) (((val) >> ((sizeof(val) - 1) << 3)) & 255)
#define bitRead(val, bitno) (((val) >> (bitno)) & 1)
/** #else
* Combine two bytes to a 16 bit uint16_t. #include <Arduino.h>
* #include <user_interface.h>
* @param high - the high uint8_t. #define printf Serial.printf
* @param low - the low uint8_t. #endif
* @return The bytes combined as uint16_t.
*/
uint16_t makeWord(uint8_t high, uint8_t low);
/**
* Reverse the uint8_t order of an integer.
*
* @param val - the value to reverse.
* @return The value with reversed uint8_t order.
*/
uint32_t reverseByteOrder(uint32_t val);
/**
* Reverse the uint8_t order of a short integer.
*
* @param val - the value to reverse.
* @return The value with reversed uint8_t order.
*/
uint16_t reverseByteOrder(uint16_t val);
//
// Inline functions
//
inline uint16_t makeWord(uint8_t high, uint8_t low)
{
return (high << 8) | low;
}
inline uint32_t reverseByteOrder(uint32_t val)
{
uint32_t swapped = ((val >> 24) & 0xff) | // move uint8_t 3 to uint8_t 0
((val << 8) & 0xff0000) | // move uint8_t 1 to uint8_t 2
((val >> 8) & 0xff00) | // move uint8_t 2 to uint8_t 1
((val << 24) & 0xff000000); // uint8_t 0 to uint8_t 3
return swapped;//__REV(val);
}
inline uint16_t reverseByteOrder(uint16_t val)
{
uint16_t swapped = (val >> 8) | (val << 8);
return swapped;
}
uint8_t* popByte(uint8_t& b, uint8_t* data); uint8_t* popByte(uint8_t& b, uint8_t* data);
uint8_t* popWord(uint16_t& w, uint8_t* data); uint8_t* popWord(uint16_t& w, uint8_t* data);

View File

@ -81,12 +81,25 @@ uint8_t DeviceObject::propertySize(PropertyID id)
{ {
switch (id) switch (id)
{ {
case PID_DEVICE_CONTROL: case PID_OBJECT_TYPE:
return 1; case PID_DEVICE_CONTROL:
case PID_ROUTING_COUNT: case PID_ROUTING_COUNT:
return 1; case PID_PROG_MODE:
case PID_PROG_MODE: case PID_MAX_APDU_LENGTH:
return 1; case PID_SUBNET_ADDR:
case PID_DEVICE_ADDR:
return 1;
case PID_MANUFACTURER_ID:
case PID_VERSION:
case PID_DEVICE_DESCRIPTOR:
return 2;
case PID_IO_LIST:
return 4;
case PID_SERIAL_NUMBER:
case PID_HARDWARE_TYPE:
return 6;
case PID_ORDER_INFO:
return 10;
} }
return 0; return 0;
} }

View File

@ -57,9 +57,9 @@ void EspPlatform::fatalError()
void EspPlatform::setupMultiCast(uint32_t addr, uint16_t port) void EspPlatform::setupMultiCast(uint32_t addr, uint16_t port)
{ {
_mulitcastAddr = addr; _mulitcastAddr = htonl(addr);
_mulitcastPort = port; _mulitcastPort = port;
IPAddress mcastaddr(htonl(addr)); IPAddress mcastaddr(_mulitcastAddr);
Serial.printf("setup multicast addr: %s port: %d ip: %s\n", mcastaddr.toString().c_str(), port, Serial.printf("setup multicast addr: %s port: %d ip: %s\n", mcastaddr.toString().c_str(), port,
WiFi.localIP().toString().c_str()); WiFi.localIP().toString().c_str());
@ -85,7 +85,7 @@ void printHex(const char* suffix, uint8_t *data, uint8_t length)
bool EspPlatform::sendBytes(uint8_t * buffer, uint16_t len) bool EspPlatform::sendBytes(uint8_t * buffer, uint16_t len)
{ {
printHex("-> ",buffer, len); printHex("<- ",buffer, len);
int result = 0; int result = 0;
result = _udp.beginPacketMulticast(_mulitcastAddr, _mulitcastPort, WiFi.localIP()); result = _udp.beginPacketMulticast(_mulitcastAddr, _mulitcastPort, WiFi.localIP());
result = _udp.write(buffer, len); result = _udp.write(buffer, len);
@ -106,7 +106,7 @@ int EspPlatform::readBytes(uint8_t * buffer, uint16_t maxLen)
} }
_udp.read(buffer, len); _udp.read(buffer, len);
printHex("<- ", buffer, len); printHex("-> ", buffer, len);
return len; return len;
} }

View File

@ -23,7 +23,7 @@ bool GroupObject::responseUpdateEnable()
if (!_table) if (!_table)
return false; return false;
return bitRead(_table->_tableData[_asap], 15) > 0; return bitRead(ntohs(_table->_tableData[_asap]), 15) > 0;
} }
bool GroupObject::transmitEnable() bool GroupObject::transmitEnable()
@ -31,7 +31,7 @@ bool GroupObject::transmitEnable()
if (!_table) if (!_table)
return false; return false;
return bitRead(_table->_tableData[_asap], 14) > 0; return bitRead(ntohs(_table->_tableData[_asap]), 14) > 0 ;
} }
bool GroupObject::valueReadOnInit() bool GroupObject::valueReadOnInit()
@ -39,7 +39,7 @@ bool GroupObject::valueReadOnInit()
if (!_table) if (!_table)
return false; return false;
return bitRead(_table->_tableData[_asap], 13) > 0; return bitRead(ntohs(_table->_tableData[_asap]), 13) > 0;
} }
bool GroupObject::writeEnable() bool GroupObject::writeEnable()
@ -47,7 +47,7 @@ bool GroupObject::writeEnable()
if (!_table) if (!_table)
return false; return false;
return bitRead(_table->_tableData[_asap], 12) > 0; return bitRead(ntohs(_table->_tableData[_asap]), 12) > 0 ;
} }
bool GroupObject::readEnable() bool GroupObject::readEnable()
@ -55,7 +55,7 @@ bool GroupObject::readEnable()
if (!_table) if (!_table)
return false; return false;
return bitRead(_table->_tableData[_asap], 11) > 0; return bitRead(ntohs(_table->_tableData[_asap]), 11) > 0;
} }
bool GroupObject::communicationEnable() bool GroupObject::communicationEnable()
@ -63,7 +63,7 @@ bool GroupObject::communicationEnable()
if (!_table) if (!_table)
return false; return false;
return bitRead(_table->_tableData[_asap], 10) > 0; return bitRead(ntohs(_table->_tableData[_asap]), 10) > 0;
} }
@ -72,7 +72,7 @@ Priority GroupObject::priority()
if (!_table) if (!_table)
return LowPriority; return LowPriority;
return (Priority)((_table->_tableData[_asap] >> 6) & (3 << 2)) ; return (Priority)((ntohs(_table->_tableData[_asap]) >> 6) & (3 << 2)) ;
} }
uint8_t* GroupObject::valueRef() uint8_t* GroupObject::valueRef()
@ -144,7 +144,7 @@ void GroupObject::commFlag(ComFlag value)
int32_t GroupObject::objectReadFloat() int32_t GroupObject::objectReadFloat()
{ {
uint16_t dptValue = makeWord(_data[0], _data[1]); uint16_t dptValue = getWord(_data);
return dptFromFloat(dptValue); return dptFromFloat(dptValue);
} }
@ -186,6 +186,6 @@ size_t GroupObject::valueSize()
size_t GroupObject::sizeInTelegram() size_t GroupObject::sizeInTelegram()
{ {
uint8_t code = lowByte(_table->_tableData[_asap]); uint8_t code = lowByte(ntohs(_table->_tableData[_asap]));
return asapValueSize(code); return asapValueSize(code);
} }

View File

@ -27,7 +27,7 @@ uint16_t GroupObjectTableObject::entryCount()
if (loadState() != LS_LOADED) if (loadState() != LS_LOADED)
return 0; return 0;
return _tableData[0]; return ntohs(_tableData[0]);
} }
@ -91,10 +91,6 @@ void GroupObjectTableObject::beforeStateChange(LoadState& newState)
return; return;
_tableData = (uint16_t*)_data; _tableData = (uint16_t*)_data;
uint16_t goCount = reverseByteOrder(_tableData[0]);
// big endian -> little endian
for (size_t i = 0; i <= goCount; i++)
_tableData[i] = reverseByteOrder(_tableData[i]);
if (!initGroupObjects()) if (!initGroupObjects())
{ {
@ -108,7 +104,7 @@ bool GroupObjectTableObject::initGroupObjects()
if (!_tableData) if (!_tableData)
return false; return false;
uint16_t goCount = _tableData[0]; uint16_t goCount = ntohs(_tableData[0]);
if (goCount != _groupObjectCount) if (goCount != _groupObjectCount)
return false; return false;

View File

@ -118,24 +118,28 @@ uint8_t IpParameterObject::propertySize(PropertyID id)
{ {
switch (id) switch (id)
{ {
case PID_IP_ASSIGNMENT_METHOD:
case PID_LOAD_STATE_CONTROL:
case PID_IP_CAPABILITIES:
case PID_TTL:
case PID_KNXNETIP_DEVICE_CAPABILITIES:
case PID_FRIENDLY_NAME:
return 1;
case PID_OBJECT_TYPE:
case PID_PROJECT_INSTALLATION_ID: case PID_PROJECT_INSTALLATION_ID:
return 2;
case PID_KNX_INDIVIDUAL_ADDRESS: case PID_KNX_INDIVIDUAL_ADDRESS:
return 2; return 2;
case PID_IP_ASSIGNMENT_METHOD: case PID_CURRENT_IP_ADDRESS:
return 1; case PID_CURRENT_SUBNET_MASK:
case PID_CURRENT_DEFAULT_GATEWAY:
case PID_IP_ADDRESS: case PID_IP_ADDRESS:
return 4;
case PID_SUBNET_MASK: case PID_SUBNET_MASK:
return 4;
case PID_DEFAULT_GATEWAY: case PID_DEFAULT_GATEWAY:
return 4; case PID_SYSTEM_SETUP_MULTICAST_ADDRESS:
case PID_ROUTING_MULTICAST_ADDRESS: case PID_ROUTING_MULTICAST_ADDRESS:
return 4; return 4;
case PID_TTL: case PID_MAC_ADDRESS:
return 1; return 6;
case PID_FRIENDLY_NAME:
return 1;
} }
return 0; return 0;
} }

View File

@ -2,6 +2,7 @@
#include "tpdu.h" #include "tpdu.h"
#include "cemi_frame.h" #include "cemi_frame.h"
#include "data_link_layer.h" #include "data_link_layer.h"
#include "bits.h"
NetworkLayer::NetworkLayer(TransportLayer& layer): _transportLayer(layer) NetworkLayer::NetworkLayer(TransportLayer& layer): _transportLayer(layer)
{ {

View File

@ -47,11 +47,11 @@ uint8_t TableObject::propertySize(PropertyID id)
switch (id) switch (id)
{ {
case PID_LOAD_STATE_CONTROL: case PID_LOAD_STATE_CONTROL:
return 10; return 1;
case PID_TABLE_REFERENCE:
//case PID_MCB_TABLE: return 4;
// TODO case PID_ERROR_CODE:
// break; return 1;
} }
return 0; return 0;
} }