Files
2024-05-18 23:53:26 +08:00

320 lines
10 KiB
C

/**
* @file GoSensorInfo.c
*
* @internal
* Copyright (C) 2016-2021 by LMI Technologies Inc.
* Licensed under the MIT License.
* Redistributed files must retain the above copyright notice.
*/
#include <GoSdk/GoSensorInfo.h>
#include <kApi/Utils/kUtils.h>
kBeginClassEx(Go, GoSensorInfo)
kEndClassEx()
GoFx(kStatus) GoSensorInfo_Construct(GoSensorInfo* info, kAlloc allocator)
{
kAlloc alloc = kAlloc_Fallback(allocator);
kStatus status;
kCheck(kAlloc_GetObject(alloc, kTypeOf(GoSensorInfo), info));
if (!kSuccess(status = GoSensorInfo_Init(*info, kTypeOf(GoSensorInfo), alloc)))
{
kAlloc_FreeRef(alloc, info);
}
return status;
}
GoFx(kStatus) GoSensorInfo_Init(GoSensorInfo info, kType type, kAlloc alloc)
{
kObjR(GoSensorInfo, info);
kCheck(kObject_Init(info, type, alloc));
obj->id = 0;
kZero(obj->firmwareVersion);
obj->partNumber[0] = 0;
obj->buddyId = 0;
obj->address = kIpAddress_AnyV4();
obj->mainId = 0;
obj->buddyableStatus = GO_BUDDY_STATE_ERROR;
obj->role = GO_ROLE_MAIN;
obj->state = GO_STATE_OFFLINE;
obj->modelNumber[0] = 0;
obj->modelDisplayName[0] = 0;
return kOK;
}
GoFx(kStatus) GoSensorInfo_Read(GoSensorInfo info, kSerializer serializer)
{
kObj(GoSensorInfo, info);
k32s temp;
kByte tempArray[4];
kSize i;
kCheck(kSerializer_Read32u(serializer, &obj->id));
kCheck(kSerializer_ReadByteArray(serializer, tempArray, kCountOf(tempArray)));
for (i = 0; i < 16; i++)
{
if (i < 4)
{
obj->address.address[i] = tempArray[i];
}
else
{
obj->address.address[i] = 0;
}
}
//hack for now
// modelName is deprecated, underlying var is renamed to partNumber for clarity.
kCheck(kSerializer_ReadCharArray(serializer, obj->partNumber, kCountOf(obj->partNumber)));
kCheck(kSerializer_ReadByteArray(serializer, tempArray, kCountOf(tempArray)));
obj->firmwareVersion = kVersion_Create(tempArray[0], tempArray[1], tempArray[2], tempArray[3]);
kCheck(kSerializer_Read32s(serializer, &temp));
switch(temp)
{
case -1: obj->state = GO_STATE_INCOMPLETE; break;
case 0: obj->state = GO_STATE_READY; break;
case 1: obj->state = GO_STATE_RUNNING; break;
default: obj->state = GO_STATE_CONNECTED; break;
}
kCheck(kSerializer_Read32s(serializer, &obj->role));
kCheck(kSerializer_Read32s(serializer, &obj->buddyId));
// Even for very old sensors, we can still provide fallback modelNumber and display name.
kCheck(GoSensorInfo_FillModelNumber(info, obj->partNumber, obj->modelNumber, kCountOf(obj->modelNumber)));
kCheck(GoSensorInfo_FillModelDisplayName(info, obj->partNumber, obj->modelDisplayName, kCountOf(obj->modelDisplayName)));
return kOK;
}
GoFx(kStatus) GoSensorInfo_ReadV2(GoSensorInfo info, kSerializer serializer, k16u sensorInfoSize, kBool isLocalInfo)
{
kObj(GoSensorInfo, info);
k32s temp;
k32u bytesRead = 0;
kByte tempArray[4];
kSize i;
kCheck(kSerializer_Read32u(serializer, &obj->id));
kCheck(kSerializer_ReadByteArray(serializer, tempArray, kCountOf(tempArray)));
for (i = 0; i < 16; i++)
{
if (i < 4)
{
obj->address.address[i] = tempArray[i];
}
else
{
obj->address.address[i] = 0;
}
}
//hack for now
// modelName is deprecated, underlying var is renamed to partNumber for clarity.
kCheck(kSerializer_ReadCharArray(serializer, obj->partNumber, kCountOf(obj->partNumber)));
kCheck(kSerializer_ReadByteArray(serializer, tempArray, kCountOf(tempArray)));
obj->firmwareVersion = kVersion_Create(tempArray[0], tempArray[1], tempArray[2], tempArray[3]);
kCheck(kSerializer_Read32s(serializer, &temp));
switch (temp)
{
case -1: obj->state = GO_STATE_INCOMPLETE; break;
case 0: obj->state = GO_STATE_READY; break;
case 1: obj->state = GO_STATE_RUNNING; break;
default: obj->state = GO_STATE_CONNECTED; break;
}
kCheck(kSerializer_Read32s(serializer, &obj->role));
bytesRead = 52;
//SensorInfoV2 is variable size, so need to track the number of bytes read in case a future sensor version is sending more data than what this version expects
if (!isLocalInfo)
{
kCheck(kSerializer_Read32u(serializer, &obj->mainId));
kCheck(kSerializer_Read32s(serializer, &obj->buddyableStatus));
bytesRead += 8;
}
// During 5.3 Beta, before 5.3.10.31
if (sensorInfoSize - bytesRead == 0)
{
// Provide fallback values for modelNumber and modelDisplayName.
kCheck(GoSensorInfo_FillModelNumber(info, obj->partNumber, obj->modelNumber, kCountOf(obj->modelNumber)));
kCheck(GoSensorInfo_FillModelDisplayName(info, obj->partNumber, obj->modelDisplayName, kCountOf(obj->modelDisplayName)));
}
// During 5.3 Beta for 5.3.10.31 - 5.3.17.23.
else if (sensorInfoSize - bytesRead == kCountOf(obj->modelDisplayName))
{
// Read modelDisplayName, and provide fallback values for modelNumber.
kCheck(GoSensorInfo_FillModelNumber(info, obj->partNumber, obj->modelNumber, kCountOf(obj->modelNumber)));
kCheck(kSerializer_ReadCharArray(serializer, obj->modelDisplayName, kCountOf(obj->modelDisplayName)));
bytesRead += kCountOf(obj->modelDisplayName);
}
// During 5.3 Beta for 5.3.17.23 and onwards.. to 5.3 Release
else if (sensorInfoSize - bytesRead >= kCountOf(obj->modelDisplayName) + kCountOf(obj->modelNumber))
{
// Read modelNumber and modelDisplayName.
kCheck(kSerializer_ReadCharArray(serializer, obj->modelNumber, kCountOf(obj->modelNumber)));
bytesRead += kCountOf(obj->modelNumber);
kCheck(kSerializer_ReadCharArray(serializer, obj->modelDisplayName, kCountOf(obj->modelDisplayName)));
bytesRead += kCountOf(obj->modelDisplayName);
}
kCheck(kSerializer_AdvanceRead(serializer, sensorInfoSize - bytesRead));
return kOK;
}
GoFx(k32u) GoSensorInfo_Id(GoSensorInfo info)
{
kObj(GoSensorInfo, info);
return obj->id;
}
GoFx(kVersion) GoSensorInfo_Firmware(GoSensorInfo info)
{
kObj(GoSensorInfo, info);
return obj->firmwareVersion;
}
// deprecated
GoFx(kStatus) GoSensorInfo_Model(GoSensorInfo info, kChar* model, kSize capacity)
{
kObj(GoSensorInfo, info);
// modelName is deprecated, provide the original behavior which was to return partNumber.
return GoSensorInfo_PartNumber(info, model, capacity);
}
GoFx(kStatus) GoSensorInfo_PartNumber(GoSensorInfo info, kChar* partNumber, kSize capacity)
{
kObj(GoSensorInfo, info);
// NOTE: the partnumber returned in the remote info is actually the "Derived LMI PartNumber",
// which hides branding customizations, and may not fully match the true part number
// that is available in GoSensor_PartNumber().
return kStrCopy(partNumber, capacity, obj->partNumber);
}
GoFx(kStatus) GoSensorInfo_ModelNumber(GoSensorInfo info, kChar* modelNumber, kSize capacity)
{
kObj(GoSensorInfo, info);
return kStrCopy(modelNumber, capacity, obj->modelNumber);
}
GoFx(kStatus) GoSensorInfo_ModelDisplayName(GoSensorInfo info, kChar* modelDisplayName, kSize capacity)
{
kObj(GoSensorInfo, info);
return kStrCopy(modelDisplayName, capacity, obj->modelDisplayName);
}
GoFx(GoRole) GoSensorInfo_Role(GoSensorInfo info)
{
kObj(GoSensorInfo, info);
return obj->role;
}
GoFx(kBool) GoSensorInfo_HasBuddy(GoSensorInfo info)
{
kObj(GoSensorInfo, info);
return (obj->buddyId != 0);
}
GoFx(k32u) GoSensorInfo_BuddyId(GoSensorInfo info)
{
kObj(GoSensorInfo, info);
return obj->buddyId;
}
GoFx(GoState) GoSensorInfo_State(GoSensorInfo info)
{
kObj(GoSensorInfo, info);
return obj->state;
}
GoFx(GoBuddyState) GoSensorInfo_BuddyableStatus(GoSensorInfo info)
{
kObj(GoSensorInfo, info);
return obj->buddyableStatus;
}
GoFx(k32s) GoSensorInfo_buddyableStatus(GoSensorInfo info)
{
return GoSensorInfo_BuddyableStatus(info);
}
GoFx(k32u) GoSensorInfo_MainId(GoSensorInfo info)
{
kObj(GoSensorInfo, info);
return obj->mainId;
}
GoFx(kStatus) GoSensorInfo_FillModelNumber(GoSensorInfo info, kChar *partNumber, kChar *fallBackModelNumber, kSize capacity)
{
kObj(GoSensorInfo, info);
const char* pos = kNULL;
kString tempString = kNULL;
k32s tempCleanNum = kNULL;
kArrayList tokens = kNULL;
kStatus exception;
kTry
{
kTest(kString_Construct(&tempString, partNumber, kObject_Alloc(info)));
kTest(kString_Split(tempString, "-", &tokens, kObject_Alloc(info)));
if(kArrayList_Count(tokens) == 0)
{
// This is the same fallback as in GsDevice_ParseModelNumber().
kTest(kStrCopy(fallBackModelNumber, capacity, "2300"));
}
else
{
// We take the first token in the part number after the two-digit class (31, 33),
// then convert to a number to get rid of A,B,C suffixes.
// ie. 33250A-3B-R-52-S
// ^^^ = "250"
//
// 312330C-2M-R-01-T
// ^^^^ = "2330"
//
kTest(k32s_Parse(&tempCleanNum, kString_Chars(kArrayList_AsT(tokens, 0, kString)) + 2));
kTest(k32s_Format(tempCleanNum, fallBackModelNumber, capacity));
}
}
kCatchEx(&exception)
{
kLogf("%s: cannot fill model number into capacity[%u] from '%s'", __FUNCTION__, capacity, partNumber);
kEndCatchEx(exception);
}
kFinallyEx
{
kDestroyRef(&tempString);
kDisposeRef(&tokens);
kEndFinallyEx();
}
return kOK;
}
GoFx(kStatus) GoSensorInfo_FillModelDisplayName(GoSensorInfo info, kChar * partNumber, kChar *fallBackModelDisplayName, kSize capacity)
{
kObj(GoSensorInfo, info);
return GoSensorInfo_FillModelNumber(info, partNumber, fallBackModelDisplayName, capacity);
}