icsneolegacy: Implemented get() and set() RTC functions
parent
af31aa23ad
commit
b3bbf91e8c
|
|
@ -689,3 +689,28 @@ bool icsneo_setTerminationFor(const neodevice_t* device, neonetid_t netid, bool
|
|||
|
||||
return device->device->settings->setTerminationFor(Network(netid), enabled);
|
||||
}
|
||||
|
||||
bool icsneo_getRTC(const neodevice_t* device, uint64_t* output)
|
||||
{
|
||||
if(!icsneo_isValidNeoDevice(device))
|
||||
return false;
|
||||
|
||||
const std::optional<std::chrono::time_point<std::chrono::system_clock>> rtc = device->device->getRTC();
|
||||
if(!rtc)
|
||||
return false;
|
||||
|
||||
auto duration = std::chrono::duration_cast<std::chrono::seconds>(rtc->time_since_epoch());
|
||||
*output = static_cast<uint64_t>(duration.count());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool icsneo_setRTC(const neodevice_t* device, uint64_t input)
|
||||
{
|
||||
if(!icsneo_isValidNeoDevice(device))
|
||||
return false;
|
||||
|
||||
std::chrono::seconds duration(input);
|
||||
const std::chrono::system_clock::time_point time(duration);
|
||||
return device->device->setRTC(time);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4100) // unreferenced formal parameter
|
||||
#pragma warning(disable : 4996) // STL time functions
|
||||
#endif
|
||||
|
||||
using namespace icsneo;
|
||||
|
|
@ -559,6 +560,54 @@ void LegacyDLLExport icsneoSetISO15765RxParameters(void* hObject, int lNetwork,
|
|||
return;
|
||||
}
|
||||
|
||||
int LegacyDLLExport icsneoGetRTC(void* hObject, icsSpyTime* time)
|
||||
{
|
||||
if(!icsneoValidateHObject(hObject))
|
||||
return false;
|
||||
neodevice_t* device = reinterpret_cast<neodevice_t*>(hObject);
|
||||
|
||||
uint64_t time64 = 0;
|
||||
if(!icsneo_getRTC(device, &time64))
|
||||
return false;
|
||||
|
||||
std::time_t seconds = time64;
|
||||
/* To accommodate local time bugzilla #6600 https://intrepidcs.homeip.net:100/bugzilla/show_bug.cgi?id=6600 */
|
||||
// local time must be used here
|
||||
const auto timeInfo = std::localtime(&seconds);
|
||||
if(!timeInfo)
|
||||
return false;
|
||||
|
||||
time->sec = (unsigned char)timeInfo->tm_sec; // Will never hit 60 (leap second) because tm_sec comes from RTCCTIME
|
||||
time->min = (unsigned char)timeInfo->tm_min;
|
||||
time->hour = (unsigned char)timeInfo->tm_hour;
|
||||
time->day = (unsigned char)timeInfo->tm_mday;
|
||||
time->month = (unsigned char)timeInfo->tm_mon + 1;
|
||||
time->year = (unsigned char)timeInfo->tm_year % 100;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int LegacyDLLExport icsneoSetRTC(void* hObject, const icsSpyTime* time)
|
||||
{
|
||||
if(!icsneoValidateHObject(hObject))
|
||||
return false;
|
||||
neodevice_t* device = reinterpret_cast<neodevice_t*>(hObject);
|
||||
|
||||
std::tm timeInfo{};
|
||||
timeInfo.tm_sec = time->sec;
|
||||
timeInfo.tm_min = time->min;
|
||||
timeInfo.tm_hour = time->hour;
|
||||
timeInfo.tm_mday = time->day;
|
||||
timeInfo.tm_mon = time->month - 1;
|
||||
timeInfo.tm_year = time->year + 100;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define timegm _mkgmtime
|
||||
#endif
|
||||
|
||||
return icsneo_setRTC(device, (uint64_t)timegm(&timeInfo));
|
||||
}
|
||||
|
||||
//Device Functions
|
||||
int LegacyDLLExport icsneoGetConfiguration(void* hObject, unsigned char* pData, int* lNumBytes)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,20 +1,27 @@
|
|||
#include "icsneo/device/device.h"
|
||||
#include "icsneo/communication/message/callback/messagecallback.h"
|
||||
#include <sstream>
|
||||
#include "icsneo/api/eventmanager.h"
|
||||
#include "icsneo/communication/command.h"
|
||||
#include "icsneo/communication/message/extendedresponsemessage.h"
|
||||
#include "icsneo/device/device.h"
|
||||
#include "icsneo/device/extensions/deviceextension.h"
|
||||
#include "icsneo/disk/fat.h"
|
||||
#include "icsneo/communication/packet/wivicommandpacket.h"
|
||||
#include "icsneo/communication/message/wiviresponsemessage.h"
|
||||
#include "icsneo/communication/message/scriptstatusmessage.h"
|
||||
#include "icsneo/communication/message/extendedresponsemessage.h"
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <chrono>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4996) // STL time functions
|
||||
#endif
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
struct RTCCTIME {
|
||||
uint8_t FracSec;// --- fractions of seconds (00-99). Note that you can write only 0x00 here!
|
||||
uint8_t Sec;// --- Seconds (00-59)
|
||||
uint8_t Min;// --- (00-59)
|
||||
uint8_t Hour;// --- (00-23)
|
||||
uint8_t DOW;// --- (01-07)
|
||||
uint8_t Day;// --- (01-31)
|
||||
uint8_t Month;// --- (01-12)
|
||||
uint8_t Year;// --- (00-99)
|
||||
};
|
||||
|
||||
static const uint8_t fromBase36Table[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 10, 11, 12,
|
||||
13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15,
|
||||
|
|
@ -1686,3 +1693,62 @@ std::optional<bool> Device::SetCollectionUploaded(uint32_t collectionEntryByteAd
|
|||
// Valid device with a properly formed respose, return success
|
||||
return std::make_optional<bool>(success);
|
||||
}
|
||||
|
||||
std::optional<std::chrono::time_point<std::chrono::system_clock>> Device::getRTC()
|
||||
{
|
||||
static const std::shared_ptr<MessageFilter> filter = std::make_shared<MessageFilter>(Network::NetID::RED_GET_RTC);
|
||||
std::shared_ptr<Message> generic = com->waitForMessageSync([this]() {
|
||||
return com->sendCommand(Command::GetRTC);
|
||||
}, filter, std::chrono::milliseconds(3000));
|
||||
if(!generic) // Did not receive a message
|
||||
return std::nullopt;
|
||||
|
||||
auto rawMes = std::dynamic_pointer_cast<RawMessage>(generic);
|
||||
if(!rawMes)
|
||||
return std::nullopt;
|
||||
|
||||
if(rawMes->data.size() != sizeof(RTCCTIME))
|
||||
return std::nullopt;
|
||||
|
||||
const auto* time = (RTCCTIME*)rawMes->data.data();
|
||||
std::tm stdTime = {};
|
||||
// std::tm has no member for the `FracSec` member of RTCCTIME struct
|
||||
stdTime.tm_sec = time->Sec;
|
||||
stdTime.tm_min = time->Min;
|
||||
stdTime.tm_hour = time->Hour;
|
||||
stdTime.tm_mday = time->Day;
|
||||
stdTime.tm_mon = time->Month - 1; // [0-11]
|
||||
stdTime.tm_year = time->Year + 100; // Number of years since 1900+100
|
||||
stdTime.tm_wday = time->DOW;
|
||||
// RTCCTIME struct has no member for `tm_yday`
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define timegm _mkgmtime
|
||||
#endif
|
||||
|
||||
return std::chrono::system_clock::from_time_t(timegm(&stdTime));
|
||||
}
|
||||
|
||||
bool Device::setRTC(const std::chrono::time_point<std::chrono::system_clock>& time)
|
||||
{
|
||||
auto now = std::chrono::system_clock::to_time_t(time);
|
||||
const auto timeInfo = std::gmtime(&now);
|
||||
if(!timeInfo)
|
||||
return false;
|
||||
|
||||
// Populate the RTCCTIME struct using the timeInfo and offsets
|
||||
// Create a vector of arguments to send as the payload to the communication command
|
||||
std::vector<uint8_t> bytestream(sizeof(RTCCTIME));
|
||||
auto rtcVals = (RTCCTIME*)bytestream.data();
|
||||
rtcVals->FracSec = (uint8_t)0X00;
|
||||
rtcVals->Sec = (uint8_t)timeInfo->tm_sec;
|
||||
rtcVals->Min = (uint8_t)timeInfo->tm_min;
|
||||
rtcVals->Hour = (uint8_t)timeInfo->tm_hour;
|
||||
rtcVals->DOW = (uint8_t)timeInfo->tm_wday + 1;
|
||||
rtcVals->Day = (uint8_t)timeInfo->tm_mday;
|
||||
rtcVals->Month = (uint8_t)timeInfo->tm_mon + 1; // [0-11]
|
||||
rtcVals->Year = (uint8_t)timeInfo->tm_year % 100; // divide by 100 and take remainder to get last 2 digits of year
|
||||
|
||||
com->sendCommand(Command::SetRTC, bytestream);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -5,6 +5,10 @@
|
|||
|
||||
#include "icsneo/icsneocpp.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4996) // STL time functions
|
||||
#endif
|
||||
|
||||
int main() {
|
||||
// Print version
|
||||
std::cout << "Running libicsneo " << icsneo::GetVersion() << std::endl;
|
||||
|
|
@ -118,6 +122,36 @@ int main() {
|
|||
}
|
||||
std::cout << "OK" << std::endl;
|
||||
|
||||
// Set the real time clock on the device using the system clock
|
||||
// First, let's see if we can get the time from the device (if it has an RTC)
|
||||
std::cout << "\n\tChecking and setting the RTC on the device" << std::endl;
|
||||
auto dTime = device->getRTC();
|
||||
if (dTime.has_value()) {
|
||||
std::time_t time = std::chrono::system_clock::to_time_t(dTime.value());
|
||||
const auto timeInfo = std::gmtime(&time);
|
||||
if(!timeInfo)
|
||||
return false;
|
||||
std::cout << "\t\tGetting current UTC time: " << std::put_time(timeInfo, "%Y-%m-%d %H:%M:%S") << std::endl;
|
||||
} else {
|
||||
std::cout << "\t\tTime not available" << std::endl;
|
||||
}
|
||||
|
||||
// Now, set the time using the system's clock so that we can check it again to ensure it's set
|
||||
auto now = std::chrono::system_clock::now();
|
||||
device->setRTC(now);
|
||||
std::cout << "\t\tTime is now set..." << std::endl;
|
||||
|
||||
// Get the time again after setting
|
||||
auto dTime2 = device->getRTC();
|
||||
if (dTime2.has_value()) {
|
||||
std::time_t time2 = std::chrono::system_clock::to_time_t(dTime2.value());
|
||||
const auto timeInfo2 = std::gmtime(&time2);
|
||||
if(!timeInfo2)
|
||||
return false;
|
||||
std::cout << "\t\tGetting current UTC time: " << std::put_time(timeInfo2, "%Y-%m-%d %H:%M:%S") << std::endl;
|
||||
} else {
|
||||
std::cout << "\t\tTime is not available" << std::endl;
|
||||
}
|
||||
// Now we can either register a handler (or multiple) for messages coming in
|
||||
// or we can enable message polling, and then call device->getMessages periodically
|
||||
|
||||
|
|
@ -127,7 +161,7 @@ int main() {
|
|||
// Keep in mind that 20k messages comes quickly at high bus loads!
|
||||
|
||||
// We can transmit messages
|
||||
std::cout << "\tTransmitting an extended CAN FD frame... ";
|
||||
std::cout << "\n\tTransmitting an extended CAN FD frame... ";
|
||||
auto txMessage5 = std::make_shared<icsneo::CANMessage>();
|
||||
txMessage5->network = icsneo::Network::NetID::HSCAN;
|
||||
txMessage5->arbid = 0x1C5001C5;
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ enum class Command : uint8_t {
|
|||
NeoWriteMemory = 0x41,
|
||||
ClearCoreMini = 0x42,
|
||||
LoadCoreMini = 0x43,
|
||||
GetRTC = 0x49,
|
||||
SetRTC = 0x50,
|
||||
RequestSerialNumber = 0xA1,
|
||||
GetMainVersion = 0xA3, // Previously known as RED_CMD_APP_VERSION_REQ
|
||||
SetSettings = 0xA4, // Previously known as RED_CMD_SET_BAUD_REQ, follow up with SaveSettings to write to EEPROM
|
||||
|
|
|
|||
|
|
@ -146,6 +146,7 @@ public:
|
|||
DWCAN16 = 541,
|
||||
LIN7 = 542,
|
||||
LIN8 = 543,
|
||||
RED_SET_RTC = 544,
|
||||
Any = 0xfffe, // Never actually set as type, but used as flag for filtering
|
||||
Invalid = 0xffff
|
||||
};
|
||||
|
|
@ -325,6 +326,8 @@ public:
|
|||
case NetID::ExtendedCommand:
|
||||
case NetID::NeoMemorySDRead:
|
||||
case NetID::NeoMemoryWriteDone:
|
||||
case NetID::RED_GET_RTC:
|
||||
case NetID::RED_SET_RTC:
|
||||
return Type::Internal;
|
||||
case NetID::Invalid:
|
||||
case NetID::Any:
|
||||
|
|
@ -453,6 +456,8 @@ public:
|
|||
return "RED_HARDWARE_EXCEP";
|
||||
case NetID::RED_GET_RTC:
|
||||
return "RED_GET_RTC";
|
||||
case NetID::RED_SET_RTC:
|
||||
return "RED_SET_RTC";
|
||||
case NetID::ISO9141_3:
|
||||
return "ISO 9141 3";
|
||||
case NetID::HSCAN2:
|
||||
|
|
|
|||
|
|
@ -50,7 +50,6 @@
|
|||
#define ICSNEO_FINDABLE_DEVICE_BY_PID(className, type, pid) \
|
||||
static constexpr const uint16_t PRODUCT_ID = pid; \
|
||||
ICSNEO_FINDABLE_DEVICE_BASE(className, type)
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
class DeviceExtension;
|
||||
|
|
@ -545,6 +544,10 @@ public:
|
|||
*/
|
||||
virtual bool getEthPhyRegControlSupported() const { return false; }
|
||||
|
||||
//RTC declarations
|
||||
std::optional<std::chrono::time_point<std::chrono::system_clock>> getRTC();
|
||||
bool setRTC(const std::chrono::time_point<std::chrono::system_clock>& time);
|
||||
|
||||
/**
|
||||
* Returns true if this device supports the Wireless neoVI featureset
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -2442,6 +2442,16 @@ typedef struct
|
|||
uint8_t bIPV4_Address[4]; // The Ipv4 address assigned to the Network interface. If not available, all bytes are set to zero.
|
||||
} NETWORK_ADAPTER_INFO;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char sec;// --- Seconds (00-59)
|
||||
unsigned char min;// --- (00-59)
|
||||
unsigned char hour;// --- (00-23)
|
||||
unsigned char day;// --- (01-31)
|
||||
unsigned char month;// --- (01-12)
|
||||
unsigned char year;// --- (00-99)
|
||||
} icsSpyTime;
|
||||
|
||||
#ifndef INTREPID_NO_CHECK_STRUCT_SIZE
|
||||
|
||||
#if defined(__cplusplus) && (__cplusplus > 199711L)
|
||||
|
|
|
|||
|
|
@ -808,6 +808,24 @@ extern bool DLLExport icsneo_isTerminationEnabledFor(const neodevice_t* device,
|
|||
*/
|
||||
extern bool DLLExport icsneo_setTerminationFor(const neodevice_t* device, neonetid_t netid, bool enabled);
|
||||
|
||||
/**
|
||||
* \brief Get the real-time clock for the given device.
|
||||
* \param[out] device A pointer to the neodevice_t structure specifying the device to read the RTC from.
|
||||
* \param[out] output A pointer to a uint64_t where the RTC will be stored. This value is in seconds.
|
||||
|
||||
* \returns True if the RTC was successfully retrieved.
|
||||
*/
|
||||
extern bool icsneo_getRTC(const neodevice_t* device, uint64_t* output);
|
||||
|
||||
/**
|
||||
* \brief Set the real-time clock for the given device.
|
||||
* \param[out] device A pointer to the neodevice_t structure specifying the device to write the RTC to.
|
||||
* \param[in] input A uint64_t object holding the RTC value. This value is in seconds.
|
||||
|
||||
* \returns True if the RTC was successfully set.
|
||||
*/
|
||||
extern bool icsneo_setRTC(const neodevice_t* device, uint64_t input);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -40,6 +40,10 @@ extern void LegacyDLLExport icsneoGetISO15765Status(void* hObject, int lNetwork,
|
|||
extern void LegacyDLLExport icsneoSetISO15765RxParameters(void* hObject, int lNetwork, int lEnable, spyFilterLong* pFF_CFMsgFilter, icsSpyMessage* pTxMsg,
|
||||
int lCFTimeOutMs, int lFlowCBlockSize, int lUsesExtendedAddressing, int lUseHardwareIfPresent);
|
||||
|
||||
//RTC Functions
|
||||
extern int LegacyDLLExport icsneoGetRTC(void* hObject, icsSpyTime* time);
|
||||
extern int LegacyDLLExport icsneoSetRTC(void* hObject, const icsSpyTime* time);
|
||||
|
||||
//Device Functions
|
||||
extern int LegacyDLLExport icsneoGetConfiguration(void* hObject, unsigned char* pData, int* lNumBytes);
|
||||
extern int LegacyDLLExport icsneoSendConfiguration(void* hObject, unsigned char* pData, int lNumBytes);
|
||||
|
|
|
|||
Loading…
Reference in New Issue