save work

This commit is contained in:
nanosonde 2019-12-03 15:25:53 +01:00
parent ee72a23617
commit 589aec4585
7 changed files with 71 additions and 54 deletions

View File

@ -118,50 +118,34 @@ void Bau27B0::loop()
void Bau27B0::domainAddressSerialNumberWriteIndication(Priority priority, HopCountType hopType, uint8_t* rfDoA,
uint8_t* knxSerialNumber)
{
uint8_t curSerialNumber[6];
pushWord(_deviceObj.manufacturerId(), &curSerialNumber[0]);
pushInt(_deviceObj.bauNumber(), &curSerialNumber[2]);
// If the received serial number matches our serial number
// then store the received RF domain address in the RF medium object
if (!memcmp(knxSerialNumber, curSerialNumber, 6))
if (!memcmp(knxSerialNumber, _deviceObj.knxSerialNumber(), 6))
_rfMediumObj.rfDomainAddress(rfDoA);
}
void Bau27B0::domainAddressSerialNumberReadIndication(Priority priority, HopCountType hopType, uint8_t* knxSerialNumber)
{
uint8_t curSerialNumber[6];
pushWord(_deviceObj.manufacturerId(), &curSerialNumber[0]);
pushInt(_deviceObj.bauNumber(), &curSerialNumber[2]);
// If the received serial number matches our serial number
// then send a response with the current RF domain address stored in the RF medium object
if (!memcmp(knxSerialNumber, curSerialNumber, 6))
if (!memcmp(knxSerialNumber, _deviceObj.knxSerialNumber(), 6))
_appLayer.domainAddressSerialNumberReadResponse(priority, hopType, _rfMediumObj.rfDomainAddress(), knxSerialNumber);
}
void Bau27B0::individualAddressSerialNumberWriteIndication(Priority priority, HopCountType hopType, uint16_t newIndividualAddress,
uint8_t* knxSerialNumber)
{
uint8_t curSerialNumber[6];
pushWord(_deviceObj.manufacturerId(), &curSerialNumber[0]);
pushInt(_deviceObj.bauNumber(), &curSerialNumber[2]);
// If the received serial number matches our serial number
// then store the received new individual address in the device object
if (!memcmp(knxSerialNumber, curSerialNumber, 6))
if (!memcmp(knxSerialNumber, _deviceObj.knxSerialNumber(), 6))
_deviceObj.induvidualAddress(newIndividualAddress);
}
void Bau27B0::individualAddressSerialNumberReadIndication(Priority priority, HopCountType hopType, uint8_t* knxSerialNumber)
{
uint8_t curSerialNumber[6];
pushWord(_deviceObj.manufacturerId(), &curSerialNumber[0]);
pushInt(_deviceObj.bauNumber(), &curSerialNumber[2]);
// If the received serial number matches our serial number
// then send a response with the current RF domain address stored in the RF medium object and the serial number
if (!memcmp(knxSerialNumber, curSerialNumber, 6))
if (!memcmp(knxSerialNumber, _deviceObj.knxSerialNumber(), 6))
_appLayer.IndividualAddressSerialNumberReadResponse(priority, hopType, _rfMediumObj.rfDomainAddress(), knxSerialNumber);
}

View File

@ -362,7 +362,6 @@ void BauSystemB::nextRestartState()
void BauSystemB::systemNetworkParameterReadIndication(Priority priority, HopCountType hopType, uint16_t objectType,
uint16_t propertyId, uint8_t* testInfo, uint16_t testInfoLength)
{
uint8_t knxSerialNumber[6];
uint8_t operand;
popByte(operand, testInfo + 1); // First byte (+ 0) contains only 4 reserved bits (0)
@ -375,10 +374,8 @@ void BauSystemB::systemNetworkParameterReadIndication(Priority priority, HopCoun
if (_deviceObj.progMode() && (objectType == OT_DEVICE) && (propertyId == PID_SERIAL_NUMBER))
{
// Send reply. testResult data is KNX serial number
pushWord(_deviceObj.manufacturerId(), &knxSerialNumber[0]);
pushInt(_deviceObj.bauNumber(), &knxSerialNumber[2]);
_appLayer.systemNetworkParameterReadResponse(priority, hopType, objectType, propertyId,
testInfo, testInfoLength, knxSerialNumber, sizeof(knxSerialNumber));
testInfo, testInfoLength, (uint8_t*) _deviceObj.knxSerialNumber(), 6);
}
break;

View File

@ -47,16 +47,16 @@ void CemiServer::dataConfirmationToTunnel(CemiFrame& frame)
void CemiServer::dataIndicationToTunnel(CemiFrame& frame)
{
static uint8_t lfn = 0;
#if MEDIUM_TYPE == 2
uint8_t data[frame.dataLength() + 10];
data[0] = L_data_ind;
data[1] = 10;
data[2] = 0x02; // RF Info add. info
data[3] = 0x08; // RF info length
data[4] = 0x02; // RF info field (batt ok)
pushByteArray(_bau.deviceObject().rfDomainAddress(), 6, &data[5]);
data[11] = lfn;
lfn = (lfn + 1) & 0x7;
data[0] = L_data_ind; // Message Code
data[1] = 10; // Total additional info length
data[2] = 0x02; // RF add. info: type
data[3] = 0x08; // RF add. info: length
data[4] = frame.rfInfo(); // RF add. info: info field (batt ok, bidir)
pushByteArray(frame.rfSerialOrDoA(), 6, &data[5]); // RF add. info:Serial or Domain Address
data[11] = frame.rfLfn(); // RF add. info: link layer frame number
memcpy(&data[12], &frame.data()[2], frame.dataLength() - 2);
CemiFrame tmpFrame(data, sizeof(data));
@ -69,6 +69,19 @@ void CemiServer::dataIndicationToTunnel(CemiFrame& frame)
printHex(" frame: ", tmpFrame.data(), tmpFrame.dataLength());
_usbTunnelInterface.sendCemiFrame(tmpFrame);
#else
print("L_data_ind: src: ");
print(frame.sourceAddress(), HEX);
print(" dst: ");
print(frame.destinationAddress(), HEX);
printHex(" frame: ", frame.data(), frame.dataLength());
_usbTunnelInterface.sendCemiFrame(frame);
#endif
}
/*

View File

@ -157,13 +157,25 @@ bool DataLinkLayer::sendTelegram(NPDU & npdu, AckType ack, uint16_t destinationA
// frame.apdu().printPDU();
// }
// The data link layer might be an open media link layer
// and will setup rfSerialOrDoA, rfInfo and rfLfn that we also
// have to send through the cEMI server tunnel
// Thus, reuse the modified cEMI frame as "frame" is only passed by reference here!
bool success = sendFrame(frame);
if (_cemiServer)
{
CemiFrame tmpFrame(frame.data(), frame.totalLenght());
// We can just copy the pointer for rfSerialOrDoA as sendFrame() sets
// a pointer to const uint8_t data in either device object (serial) or
// RF medium object (domain address)
tmpFrame.rfSerialOrDoA(frame.rfSerialOrDoA());
tmpFrame.rfInfo(frame.rfInfo());
tmpFrame.rfLfn(frame.rfLfn());
_cemiServer->dataIndicationToTunnel(tmpFrame);
}
return sendFrame(frame);
return success;
}
uint8_t* DataLinkLayer::frameData(CemiFrame& frame)

View File

@ -10,11 +10,10 @@ void DeviceObject::readProperty(PropertyID propertyId, uint32_t start, uint32_t&
pushWord(OT_DEVICE, data);
break;
case PID_SERIAL_NUMBER:
pushWord(_manufacturerId, data);
pushInt(_bauNumber, data + 2);
pushByteArray((uint8_t*)_knxSerialNumber, 6, data);
break;
case PID_MANUFACTURER_ID:
pushWord(_manufacturerId, data);
pushByteArray(&_knxSerialNumber[0], 2, data);
break;
case PID_DEVICE_CONTROL:
*data = _deviceControl;
@ -220,22 +219,36 @@ void DeviceObject::progMode(bool value)
uint16_t DeviceObject::manufacturerId()
{
return _manufacturerId;
uint16_t manufacturerId;
popWord(manufacturerId, &_knxSerialNumber[0]);
return manufacturerId;
}
void DeviceObject::manufacturerId(uint16_t value)
{
_manufacturerId = value;
pushWord(value, &_knxSerialNumber[0]);
}
uint32_t DeviceObject::bauNumber()
{
return _bauNumber;
uint32_t bauNumber;
popInt(bauNumber, &_knxSerialNumber[2]);
return bauNumber;
}
void DeviceObject::bauNumber(uint32_t value)
{
_bauNumber = value;
pushInt(value, &_knxSerialNumber[2]);
}
const uint8_t* DeviceObject::knxSerialNumber()
{
return _knxSerialNumber;
}
void DeviceObject::knxSerialNumber(const uint8_t* value)
{
pushByteArray(value, 6, _knxSerialNumber);
}
const char* DeviceObject::orderNumber()

View File

@ -29,6 +29,8 @@ public:
void manufacturerId(uint16_t value);
uint32_t bauNumber();
void bauNumber(uint32_t value);
const uint8_t* knxSerialNumber();
void knxSerialNumber(const uint8_t* value);
const char* orderNumber();
void orderNumber(const char* value);
const uint8_t* hardwareType();
@ -51,8 +53,7 @@ private:
uint8_t _routingCount = 0;
uint8_t _prgMode = 0;
uint16_t _ownAddress = 0;
uint16_t _manufacturerId = 0xfa; //Default to KNXA
uint32_t _bauNumber = 0;
uint8_t _knxSerialNumber[6] = { 0x00, 0xFA, 0x00, 0x00, 0x00, 0x00 }; //Default to KNXA (0xFA)
char _orderNumber[10] = "";
uint8_t _hardwareType[6] = { 0, 0, 0, 0, 0, 0};
uint16_t _version = 0;

View File

@ -23,12 +23,6 @@ void RfDataLinkLayer::loop()
bool RfDataLinkLayer::sendFrame(CemiFrame& frame)
{
if (!_enabled)
{
dataConReceived(frame, false);
return false;
}
// If no serial number of domain address was set,
// use our own SN/DoA
if (frame.rfSerialOrDoA() == nullptr)
@ -37,10 +31,7 @@ bool RfDataLinkLayer::sendFrame(CemiFrame& frame)
// or the RF domain address that was programmed by ETS
if (frame.systemBroadcast() == SysBroadcast)
{
uint8_t knxSerialNumber[6];
pushWord(_deviceObject.manufacturerId(), &knxSerialNumber[0]);
pushInt(_deviceObject.bauNumber(), &knxSerialNumber[2]);
frame.rfSerialOrDoA(&knxSerialNumber[0]);
frame.rfSerialOrDoA((uint8_t*)_deviceObject.knxSerialNumber());
}
else
{
@ -61,6 +52,12 @@ bool RfDataLinkLayer::sendFrame(CemiFrame& frame)
// bidirectional device, battery is ok, signal strength indication is void (no measurement)
frame.rfInfo(0x02);
if (!_enabled)
{
dataConReceived(frame, false);
return false;
}
// TODO: Is queueing really required?
// According to the spec. the upper layer may only send a new L_Data.req if it received
// the L_Data.con for the previous L_Data.req.