ESP32 S2 - reading wrong time after manual set up - time

The issue:
I have made a WEB app for setting. It has 2 options for RTC - SNTP and manual set up.
SNTP works well. But manual not...
It received GET request like - rtc_datetime=2022-12-06T07%3A02
if(httpd_query_key_value(qry, "rtc_datetime", temp, MAX_GET_QRY_VAL_LEN) == ESP_OK) {
// decoding %3A to : etc
decode(temp,value);
//strcpy(value,temp);
ESP_LOGI(TAG, "Time is: %s", value);
if(value[0]=='\0') {
char resp[] = "Set manual time mode";
httpd_resp_send(req, resp, HTTPD_RESP_USE_STRLEN);
return ESP_OK;
}
//tm.tm_year = (value[0] - '0')*1000 + (value[1] - '0')*100 + (value[2] - '0')*10 + (value[3] - '0') - 1900;//year
tm.tm_year = string2int(value,4) - 1900;
ESP_LOGI(TAG, "year is: %d", tm.tm_year);
//tm.tm_mon = (value[5] - '0')*10 + (value[6] - '0'); //month
tm.tm_mon = string2int(value+5,2) - 1;
ESP_LOGI(TAG, "mon is: %d", tm.tm_mon);
//tm.tm_mday = (value[8] - '0')*10 + (value[9] - '0');; // day
tm.tm_mday = string2int(value+8,2);
ESP_LOGI(TAG, "day is: %d", tm.tm_mday);
//tm.tm_hour = (value[11] - '0')*10 + (value[12] - '0'); // hour
tm.tm_hour = string2int(value+11,2);
ESP_LOGI(TAG, "hour is: %d", tm.tm_hour);
//tm.tm_min = (value[14] - '0')*10 + (value[15] - '0'); // minute
tm.tm_min = string2int(value+14,2);
ESP_LOGI(TAG, "min is: %d", tm.tm_min);
tm.tm_sec = 0;
time_t t = mktime(&tm);
ESP_LOGI(TAG, "The local date and time is: %s", asctime(&tm));
struct timeval new;
new.tv_usec = 0;
new.tv_sec = t;
settimeofday(&new, NULL);
//localtime(&t);
struct tm timeinfo2;
timeinfo2.tm_sec = 0;
timeinfo2.tm_min = 0;
time_t now2;// = time(NULL);
time(&now2);
localtime_r(&now2, &timeinfo2);
ESP_LOGI(TAG, "curr time - %4d-%2d-%2d %2d:%2d", timeinfo2.tm_year+1900, timeinfo2.tm_mon+1, timeinfo2.tm_mday, timeinfo2.tm_hour, timeinfo2.tm_min);
ESP_LOGI(TAG, "The local date and time is: %s", asctime(&timeinfo2));
char resp[] = "Time is set";
httpd_resp_send(req, resp, HTTPD_RESP_USE_STRLEN);
asctime(&tm) shows correct time from URL.
But time in timeinfo2 has difference 17 minutes and 53 seconds...
Line by line log:
I (16452) web server: GET request: form=rtc_form&rtc_datetime=2022-12-06T19%3A21&rtc_tz=458
I (16452) web server: r0_form
I (16452) web server: r1_form
I (16452) web server: rtc_form
I (16462) system config: sntp: 0
I (16462) system config: rtc_tz: 458
I (16462) system config: Save /spiffs/rtc.json
I (16492) system config: Set: {"rtc_sntp":0,"rtc_tz":458}
I (16492) web server: Time is: 2022-12-06T19:21
I (16492) web server: year is: 122
I (16492) web server: mon is: 11
I (16502) web server: day is: 6
I (16502) web server: hour is: 19
I (16512) web server: min is: 21
I (16512) web server: The local date and time is: Tue Dec 6 19:21:00 2022
I (16522) web server: curr time - 2022-12- 6 19:38
I (16522) web server: The local date and time is: Tue Dec 6 19:38:53 2022
I have no idea what I do wrong....
tm.tm_year = 2022 - 1900;
tm.tm_mon = 0;
tm.tm_mday = 0;
tm.tm_hour = 0;
tm.tm_min = 0;
tm.tm_sec = 0;
time_t t = mktime(&tm);
ESP_LOGI(TAG, "The local date and time is: %s", asctime(&tm));
struct timeval new;
new.tv_usec = 0;
new.tv_sec = t;
settimeofday(&new, NULL);
struct tm timeinfo2;
timeinfo2.tm_sec = 0;
timeinfo2.tm_min = 0;
time_t now2;
time(&now2);
localtime_r(&now2, &timeinfo2);
ESP_LOGI(TAG, "The local date and time is: %s", asctime(&timeinfo2));
So, this is the code without any data from GET request. Hm... What is a correct initialization for tm struct? I thing true is near...
mktime() "makes" this issue or tm struct is wrong initialized.
The same problem:
I (22892) web server: The local date and time is: Fri Dec 31 00:00:00 2021
I (22902) web server: The local date and time is: Fri Dec 31 00:17:53 2021
I add ctime() log for checking mktime() output, so it showes correct
time_t t = mktime(&tm);
ESP_LOGI(TAG, "Time from epoch t: %s", ctime(&t));
ESP_LOGI(TAG, "Time from tm: %s", asctime(&tm));
Console log:
I (18012) web server: Time from epoch t: Thu Dec 8 09:13:00 2022
I (18022) web server: Time from tm: Thu Dec 8 09:13:00 2022

I've found the same problem in espressif GitHub issues.
It looks like the issue is in the settimeofday() function.
So, I implemented the same workaround:
settimeofday(&new, NULL);
struct timeval get_set_time;
gettimeofday(&get_set_time,NULL);
int time_diff = get_set_time.tv_sec - new.tv_sec;
ESP_LOGI(TAG, "Difference in time: %d", time_diff);
new.tv_sec -= time_diff;
settimeofday(&new, NULL);
Log:
I (15322) web server: Difference in time: 1073
Moreover, the project was migrated to IDF 5.0 version — the bug is no longer there in the settimeofday(). So, the problem was solved.

Related

TimeStamp::getTimeZoneOffset returns the same offset for STD and DST?

I'm getting the time zone offset of a TIMESTAMP column using oracle::occi::Timestamp::getTimeZoneOffset method, but got the same results when retrieving a timestamp value in summer time (2020-09-30) than when retrieving other value which is in standard time (2020-03-01).
The environment is as follow:
Oracle XE 11G R2
Time Zone = Europe/Madrid (UTC offset: STD=+01:00; DST=+02:00)
Temp table with one row and two columns:
CREATE TABLE TEST_TZ_OFFSET
AS
SELECT TIMESTAMP '2020-09-30 00:00:00.000000' AS DST,
TIMESTAMP '2020-03-01 00:00:00.000000' AS STD
FROM DUAL
Oracle Instant Client for Linux x86-64 Version 12.2.0.1.0
When the column in DST is fetched it works as expected (7200 seconds = +02:00), but when STD column is fetched it has the same offset as in DST when it is suppose to be 3600 seconds (+01:00)
long getGMTOffset(oracle::occi::Connection *conn, const std::string &columnName) {
oracle::occi::Timestamp timestamp;
oracle::occi::Statement *stmt;
int tzhour = 0, tzminute = 0;
try {
std::string query = "SELECT " + columnName + " FROM TEST_TZ_OFFSET";
stmt = conn->createStatement();
stmt->setSQL(query);
oracle::occi::ResultSet *rs = stmt->executeQuery();
if (rs->next()) {
timestamp = rs->getTimestamp(1);
}
stmt->closeResultSet(rs);
conn->terminateStatement(stmt);
} catch (const std::exception &e) {
std::cerr << e.what() << "\n";
conn->terminateStatement(stmt);
}
timestamp.getTimeZoneOffset(tzhour, tzminute);
return (tzhour * 60 + tzminute) * 60;
}
std::cout << "GMT Offset of STD column = " << getGMTOffset(connection, "STD") << "\n";
std::cout << "GMT Offset of DST column = " << getGMTOffset(connection, "DST") << "\n";
Output:
GMT Offset of STD column = 7200
GMT Offset of DST column = 7200
Is this the expected behaviour?

Arduino WebServer.streamFile wierdness

Got me stumped...
Using NodeMCU with SD ... classic WebServer setup working a simple File Server over HTTP: Here is the SendFile handler:
void handleFileRequest()
{
Serial.println("handleFileRequest");
File32 file = sd.open(fileName, O_READ);
if ( file == 0 ) // Opening the file with return code of 0 is an error in SDFile.open
{
handleError(404,"File Not Found");
return;
}
int fsizeDisk = file.size();
if (file.isDirectory()|| fsizeDisk <=0)
{
handleError(500,"cannot send folder only file");
return;
}
Serial.print("file size: "); Serial.println(fsizeDisk);
ledState = LOW;
digitalWrite(LED_BUILTIN, ledState);
unsigned long timeBegin = micros();
server.sendHeader("Content-Length", (String)(fsizeDisk));
server.sendHeader("Content-disposition", "attachment; filename=\"" + fileName + "\"");
server.sendHeader("Cache-Control", "max-age=0, no-store"); // do not allow cache
server.sendHeader("Connection", "close");
size_t sent = server.streamFile(file, "application/octet-stream");
unsigned long timeEnd = micros();
unsigned long duration = timeEnd - timeBegin;
double averageDuration = (double)duration / 1000.0;
Serial.println("Duration: ");
Serial.print(averageDuration); Serial.println("s");
server.client().stop();
ledState = HIGH;
digitalWrite(LED_BUILTIN, ledState);
file.close();
delay(200);
Serial.print("Data Sent: ");
Serial.println(sent);
delay(200);
}
And here is the Serial Terminal log...
Connected to hc406-ng
IP address: 192.168.0.162
MDNS responder started #GrnAcres-Hi
SdFat version: 2.0.6
Test with GrnAcres-Hi.local/download?file=test.jpg
Or with 192.168.0.162/download?file=test.jpg
HTTP server started
handleFileRequest
Request for: Hello.txt
file size: 13
Duration:
1002.78s
Data Sent: 7
handleFileRequest
Request for: Hello.txt
file size: 13
Duration:
1002.78s
Data Sent: 7
handleFileRequest
Request for: Hello.txt
file size: 13
Duration:
1002.76s
Data Sent: 7
handleFileRequest
Request for: Hello.txt
file size: 13
Duration:
1002.73s
Data Sent: 7
handleFileRequest
Request for: Hello.txt
file size: 13
Duration:
1002.78s
Data Sent: 7
handleFileRequest
Request for: Hello.txt
file size: 13
Duration:
1002.83s
Data Sent: 7
No matter which file I use... (test.jpg is 15K)... I get 50% of the file transmitted and then the handler is called again... and again... and again?
PLEASE NOTE: the duration in seconds is OFF... this is only a debugging value it takes only 1 second per loop. I simply wanted a ratio between each sucessive call
Any comments would help greatly... thanking you all in advance.
Cheers

<Windows Hello WBDI/EngineAdapter development> A question about Adapter Workflow

I got a problem when I developed the WBDI and EngineAdapter with my fingerprint module on Win10 OS.
The problem is why the EngineAdapter doesn't go into below callback functions, after I finished Step 1 and Step 2 below?
Because the document of Microsoft mentioned that below functions will be called when enrollment workflow goes through.
(https://learn.microsoft.com/zh-tw/windows/win32/secbiomet/adapter-workflow)
Below are the callback functions not be called.
(1) "EngineAdapterCreateEnrollment"
(2) "EngineAdapterSetEnrollmentParameters"
Does anyone know how to solve it?
Many thanks.
Step1
Step2
Adapter Workflow
EngineAdapter log
DllMain, Wed Mar 17 14:22:37 2021
WbioQueryEngineInterface, Wed Mar 17 14:22:37 2021
EngineAdapterAttach, Wed Mar 17 14:22:37 2021
EngineAdapterSelectCalibrationFormat, Wed Mar 17 14:22:37 2021
EngineAdapterPipelineInit, Wed Mar 17 14:22:37 2021
DllMain, Wed Mar 17 14:22:42 2021
EngineAdapterActivate, Wed Mar 17 14:22:42 2021
EngineAdapterQueryExtendedInfo, Wed Mar 17 14:22:42 2021
EngineAdapterSetAccountPolicy, Wed Mar 17 14:22:42 2021
DllMain, Wed Mar 17 14:22:43 2021
EngineAdapterClearContext, Wed Mar 17 14:22:45 2021
EngineAdapterQueryPreferredFormat, Wed Mar 17 14:22:45 2021
EngineAdapterCreateKey, Wed Mar 17 14:22:46 2021
EngineAdapterCreateKey, Wed Mar 17 14:22:46 2021
EngineAdapterAcceptSampleData, Wed Mar 17 14:22:46 2021
EngineAdapterIdentifyFeatureSet, Wed Mar 17 14:22:46 2021
EngineAdapterClearContext, Wed Mar 17 14:22:46 2021
EngineAdapterClearContext, Wed Mar 17 14:22:46 2021
WBDI log
IOCTL_BIOMETRIC_GET_ATTRIBUTES, Wed Mar 17 14:22:37 2021
IOCTL_BIOMETRIC_GET_SENSOR_STATUS, Wed Mar 17 14:22:45 2021
IOCTL_BIOMETRIC_GET_ATTRIBUTES, Wed Mar 17 14:22:45 2021
IOCTL_BIOMETRIC_CAPTURE_DATA, Wed Mar 17 14:22:45 2021
IOCTL_BIOMETRIC_CAPTURE_DATA, Wed Mar 17 14:22:45 2021
IOCTL_BIOMETRIC_GET_SENSOR_STATUS, Wed Mar 17 14:22:46 2021
EngineAdapter code (EngineAdapter.cpp)
static WINBIO_ENGINE_INTERFACE g_EngineInterface = {
#if (NTDDI_VERSION >= NTDDI_WIN10_RS4)
WINBIO_ENGINE_INTERFACE_VERSION_6,
#elif(NTDDI_VERSION >= NTDDI_WIN10_RS3)
WINBIO_ENGINE_INTERFACE_VERSION_5,
#elif(NTDDI_VERSION >= NTDDI_WIN10_RS1)
WINBIO_ENGINE_INTERFACE_VERSION_4,
#elif(NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
WINBIO_ENGINE_INTERFACE_VERSION_3,
#elif(NTDDI_VERSION >= NTDDI_WIN8)
WINBIO_ENGINE_INTERFACE_VERSION_2,
#elif
WINBIO_ENGINE_INTERFACE_VERSION_1,
#endif
WINBIO_ADAPTER_TYPE_ENGINE,
sizeof(WINBIO_ENGINE_INTERFACE),
{0xb876fdc8, 0x34e7, 0x471a, {0x82, 0xc8, 0x9c, 0xba, 0x6a, 0x35, 0x38, 0xec}},
EngineAdapterAttach,
EngineAdapterDetach,
EngineAdapterClearContext,
EngineAdapterQueryPreferredFormat,
EngineAdapterQueryIndexVectorSize,
EngineAdapterQueryHashAlgorithms,
EngineAdapterSetHashAlgorithm,
EngineAdapterAcceptSampleHint,
EngineAdapterAcceptSampleData,
EngineAdapterExportEngineData,
EngineAdapterVerifyFeatureSet,
EngineAdapterIdentifyFeatureSet,
EngineAdapterCreateEnrollment,
EngineAdapterUpdateEnrollment,
EngineAdapterGetEnrollmentStatus,
EngineAdapterGetEnrollmentHash,
EngineAdapterCheckForDuplicate,
EngineAdapterCommitEnrollment,
EngineAdapterDiscardEnrollment,
EngineAdapterControlUnit,
EngineAdapterControlUnitPrivileged,
#if(NTDDI_VERSION >= NTDDI_WIN8)
EngineAdapterNotifyPowerChange,
EngineAdapter_RESERVED,
//EngineAdapterReserved_1;
#endif//(NTDDI_VERSION >= NTDDI_WIN8)
#if(NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
//
// V3.0 methods begin here...
//
EngineAdapterPipelineInit,
EngineAdapterPipelineCleanup,
EngineAdapterActivate,
EngineAdapterDeactivate,
EngineAdapterQueryExtendedInfo,
EngineAdapterIdentifyAll,
EngineAdapterSetEnrollmentSelector,
EngineAdapterSetEnrollmentParameters,
EngineAdapterQueryExtendedEnrollmentStatus,
EngineAdapterRefreshCache,
EngineAdapterSelectCalibrationFormat,
EngineAdapterQueryCalibrationData,
EngineAdapterSetAccountPolicy,
#endif //(NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
#if(NTDDI_VERSION >= NTDDI_WIN10_RS1)
//
// V4.0 methods begin here...
//
EngineAdapterCreateKey,
EngineAdapterIdentifyFeatureSetSecure,
#endif//(NTDDI_VERSION >= NTDDI_WIN10_RS1)
#if(NTDDI_VERSION >= NTDDI_WIN10_RS3)
//
// V5.0 methods begin here...
//
EngineAdapterAcceptPrivateSensorTypeInfo,
#endif(NTDDI_VERSION >= NTDDI_WIN10_RS3)
#if(NTDDI_VERSION >= NTDDI_WIN10_RS4)
//
// V6.0 methods begin here...
//
EngineAdapterCreateEnrollmentAuthenticated,
EngineAdapterIdentifyFeatureSetAuthenticated
#endif//(NTDDI_VERSION >= NTDDI_WIN10_RS4)
};
WBDI code
switch (ControlCode) {
//
// Mandatory IOCTLs
//
case IOCTL_BIOMETRIC_GET_ATTRIBUTES:
m_BiometricDevice->OnGetAttributes(FxRequest);
break;
case IOCTL_BIOMETRIC_RESET:
m_BiometricDevice->OnReset(FxRequest);
break;
case IOCTL_BIOMETRIC_CALIBRATE:
m_BiometricDevice->OnCalibrate(FxRequest);
break;
case IOCTL_BIOMETRIC_GET_SENSOR_STATUS:
m_BiometricDevice->OnGetSensorStatus(FxRequest);
break;
case IOCTL_BIOMETRIC_CAPTURE_DATA:
m_BiometricDevice->OnCaptureData(FxRequest);
break;
}
void
CBiometricDevice::OnGetAttributes(
_Inout_ IWDFIoRequest *FxRequest
)
{
CRequestHelper MyRequest(FxRequest); // RAII helper class
ULONG controlCode = 0;
PUCHAR inputBuffer= NULL;
SIZE_T inputBufferSize = 0;
PWINBIO_SENSOR_ATTRIBUTES sensorAttributes = NULL;
SIZE_T outputBufferSize;
//
// Get the request parameters
//
GetIoRequestParams(FxRequest,
&controlCode,
&inputBuffer,
&inputBufferSize,
(PUCHAR *)&sensorAttributes,
&outputBufferSize);
//
// Make sure we have an output buffer big enough
//
if (sensorAttributes == NULL || outputBufferSize < sizeof(DWORD))
{
// We cannot return size information.
TraceEvents(TRACE_LEVEL_ERROR,
BIOMETRIC_TRACE_DEVICE,
"%!FUNC!Output buffer NULL or too small to return size information.");
MyRequest.SetCompletionHr(E_INVALIDARG);
return;
}
// We only have one supported format, so sizeof (WINBIO_SENSOR_ATTRIBUTES) is sufficient.
if (outputBufferSize < sizeof(WINBIO_SENSOR_ATTRIBUTES))
{
// Buffer too small.
TraceEvents(TRACE_LEVEL_ERROR,
BIOMETRIC_TRACE_DEVICE,
"%!FUNC!Buffer too small - return size necessary in PayloadSize - 0x%x.", sizeof(WINBIO_SENSOR_ATTRIBUTES));
sensorAttributes->PayloadSize = (DWORD) sizeof(WINBIO_SENSOR_ATTRIBUTES);
MyRequest.SetInformation(sizeof(DWORD));
MyRequest.SetCompletionHr(S_OK);
return;
}
//
// Fill in the attribute payload structure
//
RtlZeroMemory(sensorAttributes, outputBufferSize);
sensorAttributes->PayloadSize = (DWORD) sizeof(WINBIO_SENSOR_ATTRIBUTES);
sensorAttributes->WinBioHresult = S_OK;
sensorAttributes->WinBioVersion.MajorVersion = WINBIO_WBDI_MAJOR_VERSION;
sensorAttributes->WinBioVersion.MinorVersion = WINBIO_WBDI_MINOR_VERSION;
sensorAttributes->SensorType = WINBIO_TYPE_FINGERPRINT;
sensorAttributes->SensorSubType = WINBIO_FP_SENSOR_SUBTYPE_TOUCH;// WINBIO_FP_SENSOR_SUBTYPE_SWIPE;//WINBIO_FP_SENSOR_SUBTYPE_TOUCH;
sensorAttributes->Capabilities = WINBIO_CAPABILITY_SENSOR | WINBIO_CAPABILITY_MATCHING | WINBIO_CAPABILITY_DATABASE;// WINBIO_CAPABILITY_SENSOR | WINBIO_CAPABILITY_MATCHING | WINBIO_CAPABILITY_DATABASE | WINBIO_CAPABILITY_PROCESSING;// WINBIO_CAPABILITY_SENSOR;
sensorAttributes->SupportedFormatEntries = 1;
sensorAttributes->SupportedFormat[0].Owner = WINBIO_ANSI_381_FORMAT_OWNER;
sensorAttributes->SupportedFormat[0].Type= WINBIO_ANSI_381_FORMAT_TYPE;
RtlCopyMemory(sensorAttributes->ManufacturerName, SAMPLE_MANUFACTURER_NAME, (wcslen(SAMPLE_MANUFACTURER_NAME)+1)*sizeof(WCHAR));
RtlCopyMemory(sensorAttributes->ModelName, SAMPLE_MODEL_NAME, (wcslen(SAMPLE_MODEL_NAME)+1)*sizeof(WCHAR));
RtlCopyMemory(sensorAttributes->SerialNumber, SAMPLE_SERIAL_NUMBER, (wcslen(SAMPLE_SERIAL_NUMBER)+1)*sizeof(WCHAR));
sensorAttributes->FirmwareVersion.MajorVersion = 1;
sensorAttributes->FirmwareVersion.MinorVersion = 0;
MyRequest.SetInformation(sensorAttributes->PayloadSize);
MyRequest.SetCompletionHr(S_OK);
}
void
CBiometricDevice::OnGetSensorStatus(
_Inout_ IWDFIoRequest *FxRequest
)
{
CRequestHelper MyRequest(FxRequest); // RAII helper class
ULONG controlCode = 0;
PUCHAR inputBuffer= NULL;
SIZE_T inputBufferSize = 0;
PWINBIO_DIAGNOSTICS diagnostics = NULL;
SIZE_T outputBufferSize;
//
// Get the request parameters
//
GetIoRequestParams(FxRequest,
&controlCode,
&inputBuffer,
&inputBufferSize,
(PUCHAR *)&diagnostics,
&outputBufferSize);
//
// Make sure we have an output buffer big enough
//
if (diagnostics == NULL || outputBufferSize < sizeof(DWORD))
{
// We cannot return size information.
TraceEvents(TRACE_LEVEL_ERROR,
BIOMETRIC_TRACE_DEVICE,
"%!FUNC!Output buffer NULL or too small to return size information.");
MyRequest.SetCompletionHr(E_INVALIDARG);
return;
}
if (outputBufferSize < sizeof(WINBIO_DIAGNOSTICS))
{
// Buffer too small.
TraceEvents(TRACE_LEVEL_ERROR,
BIOMETRIC_TRACE_DEVICE,
"%!FUNC!Buffer too small - return size necessary in PayloadSize - 0x%x.", sizeof(WINBIO_DIAGNOSTICS));
diagnostics->PayloadSize = (DWORD)sizeof(WINBIO_DIAGNOSTICS);
MyRequest.SetInformation(sizeof(DWORD));
MyRequest.SetCompletionHr(S_OK);
return;
}
//
// Fill in the OUT payload structure
//
RtlZeroMemory(diagnostics, outputBufferSize);
diagnostics->PayloadSize = (DWORD) sizeof(WINBIO_DIAGNOSTICS);
diagnostics->WinBioHresult = S_OK;
//diagnostics->SensorStatus = WINBIO_SENSOR_READY;
if (SensorStatusFlag)
{
SensorStatusFlag = 0;
diagnostics->SensorStatus = WINBIO_SENSOR_ACCEPT;
}
else
{
diagnostics->SensorStatus = WINBIO_SENSOR_READY;
}
MyRequest.SetInformation(diagnostics->PayloadSize);
MyRequest.SetCompletionHr(S_OK);
}
void
CBiometricDevice::OnCaptureData(
_Inout_ IWDFIoRequest *FxRequest
)
{
ULONG controlCode = 0;
PWINBIO_CAPTURE_PARAMETERS captureParams = NULL;
SIZE_T inputBufferSize = 0;
PWINBIO_CAPTURE_DATA captureData = NULL;
SIZE_T outputBufferSize = 0;
//
// We can only have one outstanding data capture request at a time.
// Check to see if we have a request pending.
//
bool requestPending = false;
EnterCriticalSection(&m_RequestLock);
if (m_PendingRequest == NULL)
{
//
// See if we have an active sleep thread.
// If so, tell it to exit.
// Wait for it to exit.
//
if (m_SleepThread != INVALID_HANDLE_VALUE)
{
LeaveCriticalSection(&m_RequestLock);
// TODO: Add code to signal thread to exit.
// NOTE: Sleeping for INFINITE time is dangerous. A real driver
// should be able to handle the case where the thread does
// not exit.
WaitForSingleObject(m_SleepThread, INFINITE);
CloseHandle(m_SleepThread);
m_SleepThread = INVALID_HANDLE_VALUE;
EnterCriticalSection(&m_RequestLock);
}
//
// We might have had to leave the CS to wait for the sleep thread.
// Double check that the pending request is still NULL.
//
if (m_PendingRequest == NULL)
{
// Save the request.
m_PendingRequest = FxRequest;
// Mark the request as cancellable.
m_PendingRequest->MarkCancelable(this);
}
else
{
requestPending = true;
}
}
else
{
requestPending = true;
}
LeaveCriticalSection(&m_RequestLock);
if (requestPending)
{
// Complete the request to tell the app that there is already
// a pending data collection request.
FxRequest->Complete(WINBIO_E_DATA_COLLECTION_IN_PROGRESS);
return;
}
//
// Get the request parameters
//
GetIoRequestParams(FxRequest,
&controlCode,
(PUCHAR *)&captureParams,
&inputBufferSize,
(PUCHAR *)&captureData,
&outputBufferSize);
//
// Check input parameters.
//
if (inputBufferSize < sizeof (WINBIO_CAPTURE_PARAMETERS))
{
// Invalid arguments
TraceEvents(TRACE_LEVEL_ERROR,
BIOMETRIC_TRACE_DEVICE,
"%!FUNC!Invalid argument(s).");
CompletePendingRequest(E_INVALIDARG, 0);
return;
}
//
// Make sure we have an output buffer big enough
//
if (outputBufferSize < sizeof(DWORD))
{
// We cannot return size information.
TraceEvents(TRACE_LEVEL_ERROR,
BIOMETRIC_TRACE_DEVICE,
"%!FUNC!Output buffer NULL or too small to return size information.");
CompletePendingRequest(E_INVALIDARG, 0);
return;
}
//
// Check output buffer size.
//
if (outputBufferSize < sizeof (WINBIO_CAPTURE_DATA))
{
// Buffer too small.
TraceEvents(TRACE_LEVEL_ERROR,
BIOMETRIC_TRACE_DEVICE,
"%!FUNC!Buffer too small - must be at least 0x%x.", sizeof (WINBIO_CAPTURE_DATA));
//
// NOTE: The output buffer size necessary for this sample is sizeof(WINBIO_CAPTURE_DATA).
// Real devices will need additional space to handle a typical capture.
// The value that should be returned here is sizeof(WINBIO_CAPTURE_DATA) + CaptureBufferSize.
//
captureData->PayloadSize = (DWORD)sizeof(WINBIO_CAPTURE_DATA)+12;
CompletePendingRequest(S_OK, sizeof(DWORD));
return;
}
//
// NOTE: This call always fails in this sample since it is not
// written for a real device.
//
//
// Set default values in output buffer.
//
SensorStatusFlag = 1;
RtlZeroMemory(captureData, outputBufferSize);
captureData->PayloadSize = (DWORD)outputBufferSize;
captureData->WinBioHresult = S_OK;
captureData->SensorStatus = WINBIO_SENSOR_ACCEPT;
captureData->RejectDetail = 0;
captureData->CaptureData.Size = (DWORD)12;
UCHAR szBuffer[] = { 0x01, 0x02, 0x03, 0x04 ,0x05, 0x06, 0x07, 0x08, 0x01, 0x02, 0x03, 0x04 };
RtlCopyMemory(captureData->CaptureData.Data, szBuffer,12);
//
// Check purpose, format and type.
//
if (captureParams->Purpose == WINBIO_NO_PURPOSE_AVAILABLE)
{
captureData->WinBioHresult = WINBIO_E_UNSUPPORTED_PURPOSE;
}
else if ((captureParams->Format.Type != WINBIO_ANSI_381_FORMAT_TYPE) ||
(captureParams->Format.Owner != WINBIO_ANSI_381_FORMAT_OWNER))
{
captureData->WinBioHresult = WINBIO_E_UNSUPPORTED_DATA_FORMAT;
}
else if (captureParams->Flags != WINBIO_DATA_FLAG_RAW)
{
captureData->WinBioHresult = WINBIO_E_UNSUPPORTED_DATA_TYPE;
}
//
// Create thread to sleep 1 seconds before completing the request.
//
m_SleepParams.SleepValue = 1;
m_SleepParams.Hr = S_OK;
m_SleepParams.Information = captureData->PayloadSize;
m_SleepThread = CreateThread(NULL, // default security attributes
0, // use default stack size
CaptureSleepThread, // thread function name
this, // argument to thread function
0, // use default creation flags
NULL); // returns the thread identifier
}
DWORD WINAPI
CaptureSleepThread(
LPVOID lpParam
)
{
CBiometricDevice *device = (CBiometricDevice *) lpParam;
PCAPTURE_SLEEP_PARAMS sleepParams = device->GetCaptureSleepParams();
//
// Make sure it is less than or equal to 1 minute.
//
if (sleepParams->SleepValue > 60)
{
sleepParams->SleepValue = 60;
}
Sleep(sleepParams->SleepValue * 1000);
device->CompletePendingRequest(sleepParams->Hr, sleepParams->Information);
return 0;
}

Ardulink 2 unable to receive message from analog Pin1 using Serial.print

I have started ardulink mqtt to listen to analog pin 1 of the arduino uno
as follow running on windows 10 with mosquitto mqtt broker 1.5.8
C:\Java\jdk1.8.0_201\bin\java -jar ardulink-mqtt-2.1.0.jar -a 1 -connection "ardulink://serial-jssc?port=COM3&pingprobe=false" -standalone
However I could not get any response despite subscribe the topics with home/devices/ardulink/A1/value/get ?
I do not see any publishing being log from the ardulink log or mosquitto
From the Arduino serial monitor , I did see all the output from Serial.print indicating the sketch was in fact fully uploaded to the Arduino uno.
arduino code
int sensorValue;
// variable to calibrate low value
int sensorLow = 1023;
// variable to calibrate high value
int sensorHigh = 0;
void setup() {
Serial.begin(115200);
// calibrate for the first five seconds after program runs
while (millis() < 5000) {
// record the maximum sensor value
sensorValue = analogRead(A1);
if (sensorValue > sensorHigh) {
sensorHigh = sensorValue;
}
// record the minimum sensor value
if (sensorValue < sensorLow) {
sensorLow = sensorValue;
}
}
}
void loop() {
//read the input from A1 and store it in a variable
sensorValue = analogRead(A1);
Serial.print(sensorValue);
// wait for a moment
delay(1000);
}
Ardulink Mqtt log
C:\ardulink\lib>C:\Java\jdk1.8.0_162\bin\java -jar ardulink-mqtt-2.1.0.jar -a 1 -d 13 -connection "ardulink://serial-jss
c?port=COM4&pingprobe=false" -clientId ardulink
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/C:/ardulink/lib/slf4j-jdk14-1.7.12.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/C:/ardulink/lib/slf4j-log4j12-1.7.5.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.slf4j.impl.JDK14LoggerFactory]
Apr 01, 2019 2:44:04 PM org.apache.camel.impl.DefaultCamelContext start
INFO: Apache Camel 2.17.1 (CamelContext: camel-1) is starting
Apr 01, 2019 2:44:04 PM org.apache.camel.management.ManagedManagementStrategy doStart
INFO: JMX is enabled
Apr 01, 2019 2:44:04 PM org.apache.camel.impl.converter.DefaultTypeConverter doStart
INFO: Loaded 182 type converters
Apr 01, 2019 2:44:04 PM org.apache.camel.impl.DefaultRuntimeEndpointRegistry doStart
INFO: Runtime endpoint registry is in extended mode gathering usage statistics of all incoming and outgoing endpoints (c
ache limit: 1000)
Apr 01, 2019 2:44:14 PM org.ardulink.core.ConnectionBasedLink startListening
INFO: Starting listening on pin ANALOG 1
Apr 01, 2019 2:44:14 PM org.ardulink.core.ConnectionBasedLink startListening
INFO: Starting listening on pin DIGITAL 13
Apr 01, 2019 2:44:14 PM org.apache.camel.impl.DefaultComponent preProcessUri
WARNING: Supplied URI 'mqtt:mqttMain?host=tcp://localhost:1883&subscribeTopicNames=home/devices/ardulink/#&connectAttemp
tsMax=1&reconnectAttemptsMax=0' contains unsafe characters, please check encoding
Apr 01, 2019 2:44:15 PM org.apache.camel.impl.DefaultCamelContext doStartCamel
INFO: AllowUseOriginalMessage is enabled. If access to the original message is not needed, then its recommended to turn
this option off as it may improve performance.
Apr 01, 2019 2:44:15 PM org.apache.camel.impl.DefaultCamelContext doStartCamel
INFO: StreamCaching is not in use. If using streams then its recommended to enable stream caching. See more details at h
ttp://camel.apache.org/stream-caching.html
Apr 01, 2019 2:44:15 PM org.apache.camel.processor.aggregate.AggregateProcessor doStart
INFO: Defaulting to MemoryAggregationRepository
Apr 01, 2019 2:44:15 PM org.apache.camel.processor.aggregate.AggregateProcessor doStart
INFO: Using CompletionInterval to run every 250 millis.
Apr 01, 2019 2:44:15 PM org.apache.camel.component.mqtt.MQTTEndpoint connect
INFO: Connecting to tcp://localhost:1883 using 10 seconds timeout
Apr 01, 2019 2:44:15 PM org.apache.camel.component.mqtt.MQTTEndpoint$2 onConnected
INFO: MQTT Connection connected to tcp://localhost:1883
Apr 01, 2019 2:44:15 PM org.apache.camel.impl.DefaultCamelContext doStartOrResumeRouteConsumers
INFO: Route: route1 started and consuming from: Endpoint[ardulink://serial-jssc?listenTo=A1%2CD13&pingprobe=false&port=C
OM4]
Apr 01, 2019 2:44:15 PM org.apache.camel.impl.DefaultCamelContext doStartOrResumeRouteConsumers
INFO: Route: route2 started and consuming from: Endpoint[direct://endOfAnalogAggregation]
Apr 01, 2019 2:44:15 PM org.apache.camel.impl.DefaultCamelContext doStartOrResumeRouteConsumers
INFO: Route: route3 started and consuming from: Endpoint[mqtt:mqttMain?host=tcp://localhost:1883&subscribeTopicNames=hom
e/devices/ardulink/#&connectAttemptsMax=1&reconnectAttemptsMax=0]
Apr 01, 2019 2:44:15 PM org.apache.camel.impl.DefaultCamelContext start
INFO: Total 3 routes, of which 3 are started.
Apr 01, 2019 2:44:15 PM org.apache.camel.impl.DefaultCamelContext start
INFO: Apache Camel 2.17.1 (CamelContext: camel-1) started in 10.898 seconds
It seems that you did not flash Ardulink sketch to the Arduino but something self-written (which does not send any message via the serial link). After flashing Ardulink sketch and starting java mqtt client again everything should work.
I managed to resolve the issue after including the standard ardulink protocol , below is the revised arduino code .
int sensorValue;
// variable to calibrate low value
int sensorLow = 1023;
// variable to calibrate high value
int sensorHigh = 0;
// LED pin
const int ledPin = 13;
String inputString = ""; // a string to hold incoming data (this is general code you can reuse)
boolean stringComplete = false; // whether the string is complete (this is general code you can reuse)
void setup() {
// Make the LED pin an output and turn it on
Serial.begin(115200);
Serial.print("alp://rply/");
Serial.print("ok?id=0");
Serial.print('\n'); // End of Message
Serial.flush();
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, HIGH);
// calibrate for the first five seconds after program runs
while (millis() < 5000) {
// record the maximum sensor value
sensorValue = analogRead(A1);
if (sensorValue > sensorHigh) {
sensorHigh = sensorValue;
}
// record the minimum sensor value
if (sensorValue < sensorLow) {
sensorLow = sensorValue;
}
}
digitalWrite(ledPin, LOW);
}
void loop() {
//read the input from A1 and store it in a variable
serialEvent();
sensorValue = analogRead(A1);
if (stringComplete==true){
if(inputString.startsWith("alp://")) {
boolean msgRecognized = true;
if (inputString.substring(6,10)=="ared"){
//Serial.println(sensorValue);
digitalWrite(ledPin, HIGH);
}else{
msgRecognized = false;
}
// Prepare reply message if caller supply a message id (this is general code you can reuse)
int idPosition = inputString.indexOf("?id=");
if(idPosition != -1) {
String id = inputString.substring(idPosition + 4);
// print the reply
Serial.print("alp://rply/");
if(msgRecognized) { // this sketch doesn't know other messages in this case command is ko (not ok)
Serial.print("ok?id=");
} else {
Serial.print("ko?id=");
}
Serial.print(id);
Serial.print('\n'); // End of Message
Serial.flush();
}
}
// clear the string:
inputString = "";
stringComplete = false;
}
if (sensorValue>0){
Serial.print("alp://ared/");
Serial.print("1");
Serial.print("/");
Serial.print(sensorValue);
Serial.print('\n'); // End of Message
Serial.flush();
}
delay(1000);
}
void serialEvent() {
while (Serial.available()>0&&!stringComplete==true) {
// get the new byte:
char inChar = (char)Serial.read();
// add it to the inputString:
inputString += inChar;
// if the incoming character is a newline, set a flag
// so the main loop can do something about it:
if (inChar == '\n') {
stringComplete = true;
}
}
}

Using C++ Boost library how to return the number of seconds since 00:00:00 January 1, 1901 GMT?

The seconds() method should call from main method and it should print the format of 00:00:00 January 1, 1901 GMT and it should return(calculate) number of seconds elapsed till user input time, I am new to the C++, I tried a lot but not able to make it happen
The code i tried:
// here i tried to start the day from the mentioned date and time
boost::posix_time::ptime timeObj = boost::posix_time::time_from_string("1901/01/01 00:00:00");
// Get current system time
boost::posix_time::ptime timeLocal = boost::posix_time::second_clock::local_time();
boost::posix_time::time_duration durObj = timeLocal.time_of_day();
std::cout << "Seconds : = " << timeLocal.time_of_day().seconds() << std::endl;
after this
I need to get a difference of seconds from 00:00:00 January 1, 1901 GMT to user input time.
in front of it should returns the format of 00:00:00 January 1, 1901 GMT.
I am doing this because I am customizing this boost library for our own product use.
Don't use time_of_day (because it gives the time-of-day).
Don't use seconds but total_seconds.
Use ptime arithmetic to get the difference. The rest was fine.
Live On Coliru
#include <boost/date_time/posix_time/posix_time.hpp>
size_t foo() {
boost::posix_time::ptime epoch { { 1901, 1, 1 } };
auto diff = boost::posix_time::second_clock::local_time() - epoch;
return diff.total_seconds();
}
int main() {
std::cout << foo() << "\n";
}
Which printed:
3710416481
Which should enable you to determine my average typing speed and my local timezone :)

Resources