blob: cb6a3fa9e2397c8609804fbefe2e5814ae1e419a [file] [log] [blame]
/**
*
* Copyright (c) 2020 Project CHIP Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "chip-zcl-zpro-codec.h"
#include <inttypes.h>
#include <stdio.h>
#include <string.h>
uint32_t encodeApsFrame(uint8_t * buffer, uint32_t buf_length, uint16_t profileID, uint16_t clusterId, uint8_t sourceEndpoint,
uint8_t destinationEndpoint, EmberApsOption options, uint16_t groupId, uint8_t sequence, uint8_t radius)
{
uint32_t size = 0;
if (buffer == NULL || buf_length == 0)
{
return size;
}
size_t nextOutByte = 0;
if (nextOutByte >= buf_length)
{
return size;
}
// Simulated APS "frame control" byte.
buffer[nextOutByte] = 0;
++nextOutByte;
if (nextOutByte >= buf_length)
{
return size;
}
memcpy(buffer + nextOutByte, &profileID, sizeof(uint16_t));
nextOutByte += sizeof(uint16_t);
if (nextOutByte >= buf_length)
{
return size;
}
memcpy(buffer + nextOutByte, &clusterId, sizeof(uint16_t));
nextOutByte += sizeof(uint16_t);
if (nextOutByte >= buf_length)
{
return size;
}
memcpy(buffer + nextOutByte, &sourceEndpoint, sizeof(uint8_t));
nextOutByte += sizeof(uint8_t);
if (nextOutByte >= buf_length)
{
return size;
}
memcpy(buffer + nextOutByte, &destinationEndpoint, sizeof(uint8_t));
nextOutByte += sizeof(uint8_t);
if (nextOutByte >= buf_length)
{
return size;
}
memcpy(buffer + nextOutByte, &options, sizeof(EmberApsOption));
nextOutByte += sizeof(EmberApsOption);
if (nextOutByte >= buf_length)
{
return size;
}
memcpy(buffer + nextOutByte, &groupId, sizeof(uint16_t));
nextOutByte += sizeof(uint16_t);
if (nextOutByte >= buf_length)
{
return size;
}
memcpy(buffer + nextOutByte, &sequence, sizeof(uint8_t));
nextOutByte += sizeof(uint8_t);
if (nextOutByte >= buf_length)
{
return size;
}
memcpy(buffer + nextOutByte, &radius, sizeof(uint8_t));
nextOutByte += sizeof(uint8_t);
buf_length = nextOutByte;
printf("Encoded %" PRIu32 " bytes of aps frame\n", buf_length);
return buf_length;
}
uint32_t _encodeOnOffCommand(uint8_t * buffer, uint32_t buf_length, int command, uint8_t destination_endpoint)
{
uint32_t result = 0;
// pick cluster id as 6 for now.
// pick source and destination end points as 1 for now.
// Profile is 65535 because that matches our simple generated code, but we
// should sort out the profile situation.
result = encodeApsFrame(buffer, buf_length, 65535, 6, 1, destination_endpoint, 0, 0, 0, 0);
if (result == 0 || result > buf_length)
{
printf("Error encoding aps frame result %" PRIu32 "\n", result);
result = 0;
return result;
}
uint32_t indexToWrite = result;
// This is a cluster-specific command so low two bits are 0b01. The command
// is standard, so does not need a manufacturer code, and we're sending
// client to server, so all the remaining bits are 0.
uint8_t * val = buffer + indexToWrite++;
*val = 0x1;
if (indexToWrite >= buf_length)
{
printf("indexToWrite %" PRIu32 "\n", indexToWrite);
return 0;
}
// Transaction sequence number. Just pick something.
val = buffer + indexToWrite++;
*val = 0x1;
if (indexToWrite >= buf_length)
{
return 0;
}
val = buffer + indexToWrite++;
*val = command;
if (indexToWrite >= buf_length)
{
return 0;
}
return indexToWrite;
}
uint32_t encodeOffCommand(uint8_t * buffer, uint32_t buf_length, uint8_t destination_endpoint)
{
return _encodeOnOffCommand(buffer, buf_length, 0, destination_endpoint);
};
uint32_t encodeOnCommand(uint8_t * buffer, uint32_t buf_length, uint8_t destination_endpoint)
{
return _encodeOnOffCommand(buffer, buf_length, 1, destination_endpoint);
}
uint32_t encodeToggleCommand(uint8_t * buffer, uint32_t buf_length, uint8_t destination_endpoint)
{
return _encodeOnOffCommand(buffer, buf_length, 2, destination_endpoint);
}