×

INDI Library v2.0.7 is Released (01 Apr 2024)

Bi-monthly release with minor bug fixes and improvements

Driver OnStep (LX200 like) for INDI

  • Posts: 48
  • Thank you received: 7
I think you are right. But it didn't work in my environment.
I debugged and found the cause.

lx200_OnStep.cpp line 4790
Processing of the LX200_OnStep :: sendScopeTime () function.
    // Get local time epoch in UNIX seconds
    time_epoch = mktime(&ltm);

mktime is returning -1 and time_epoch is calculated with the wrong value.
The cause is that ltm is being used uninitialized and ltm.tm_isdst is set to the wrong value.
Initializing ltm cleared the error.
--- lx200_OnStep.cpp.bak        2022-03-22 09:15:28.455583393 +0900
+++ lx200_OnStep.cpp    2022-03-22 09:15:00.531800080 +0900
@@ -4750,6 +4750,9 @@
     struct tm utm;
     time_t time_epoch;
 
+    memset(&ltm, 0, sizeof(ltm));
+    memset(&utm, 0, sizeof(utm));
+
     double offset = 0;
     if (getUTFOffset(&offset))
     {

This problem happens by accident, but it can happen to anyone.
Similar errors are possible with other sources.
The source code using the mktime function is as follows.

indi-master/drivers/telescope/ioptronHC8406.cpp
indi-master/drivers/telescope/lx200_OnStep.cpp
indi-master/drivers/telescope/lx200_TeenAstro.cpp
indi-master/drivers/telescope/lx200pulsar2.cpp
indi-master/drivers/telescope/lx200telescope.cpp
indi-master/drivers/telescope/rainbow.cpp
indi-master/tools/evalINDI.c
2 years 1 month ago #81621

Please Log in or Create an account to join the conversation.

  • Posts: 174
  • Thank you received: 27
Post deleted
Last edit: 2 years 1 month ago by Alex Varakin. Reason: Post deleted
2 years 1 month ago #81630

Please Log in or Create an account to join the conversation.

  • Posts: 452
  • Thank you received: 71
@Norikyu,

thank you for the debugging and solution proposal.
Since it involves not only Onstep but also others drivers we should treat the complete set.
Do you take care of making the changes and issue the pull request?

If not I will see what I can do and by when.

By the way, could you please identify which system and versions you are running (OS, Kstars, OnStep, Indiserver)
Last edit: 2 years 1 month ago by Alain Zwingelstein.
2 years 1 month ago #81642

Please Log in or Create an account to join the conversation.

  • Posts: 276
  • Thank you received: 52
@alex

Is it not one of the following that is failing as it is meant to initialize ltm in the end ?
if (getLocalTime(ctime) == false)
{
LOG_WARN("Could not obtain local time from mount!");
return false;
}

if (getLocalDate(cdate) == false)
{
LOG_WARN("Could not obtain local date from mount!");
return false;
}

// To ISO 8601 format in LOCAL TIME!
char datetime[MAXINDINAME] = {0};
snprintf(datetime, MAXINDINAME, "%sT%s", cdate, ctime);

// Now that date+time are combined, let's get tm representation of it.
->>>>>> if (strptime(datetime, "%FT%T", &ltm) == nullptr)
{
LOGF_WARN("Could not process mount date and time: %s", datetime);
return false;
}

// Get local time epoch in UNIX seconds
time_epoch = mktime(&ltm);
2 years 1 month ago #81644

Please Log in or Create an account to join the conversation.

  • Posts: 452
  • Thank you received: 71
@Norikyu,

are these the changes you suggest?
-------------------- drivers/telescope/ioptronHC8406.cpp ---------------------
index 2626278d1..ca37ce08a 100644
@@ -1156,6 +1156,9 @@ bool ioptronHC8406::sendScopeTime()
     struct tm ltm;
     struct tm utm;
     time_t time_epoch;
+    
+    memset(&ltm, 0, sizeof(ltm));
+    memset(&utm, 0, sizeof(utm));
 
     if (isSimulation())
     {
 
---------------------- drivers/telescope/lx200_OnStep.cpp ----------------------
index 425d0f6ab..7bd1b4264 100644
@@ -4749,6 +4749,9 @@ bool LX200_OnStep::sendScopeTime()
     struct tm ltm;
     struct tm utm;
     time_t time_epoch;
+    
+    memset(&ltm, 0, sizeof(ltm));
+    memset(&utm, 0, sizeof(utm));
 
     double offset = 0;
     if (getUTFOffset(&offset))
 
-------------------- drivers/telescope/lx200_TeenAstro.cpp --------------------
index 548ad1660..325785aab 100644
@@ -888,6 +888,9 @@ bool LX200_TeenAstro::sendScopeTime()
     struct tm ltm;
     struct tm utm;
     time_t time_epoch;
+    
+    memset(&ltm, 0, sizeof(ltm));
+    memset(&utm, 0, sizeof(utm));
 
     double offset = 0;
 
 
---------------------- drivers/telescope/lx200pulsar2.cpp ----------------------
index ea2c29211..062c7c664 100644
@@ -3362,6 +3362,11 @@ bool LX200Pulsar2::storeScopeLocation()
 bool LX200Pulsar2::sendScopeTime()
 {
     struct tm ltm;
+    struct tm utm;
+    
+    memset(&ltm, 0, sizeof(ltm));
+    memset(&utm, 0, sizeof(utm));
+
     if (isSimulation())
     {
         const time_t t = time(nullptr);
@@ -3380,7 +3385,7 @@ bool LX200Pulsar2::sendScopeTime()
 
     // Get time epoch and convert to TimeT
     const time_t time_epoch = mktime(&ltm);
-    struct tm utm;
+
     localtime_r(&time_epoch, &utm);
 
     // Format it into ISO 8601
 
--------------------- drivers/telescope/lx200telescope.cpp ---------------------
index 786aeca4c..26b202276 100644
@@ -1315,6 +1315,9 @@ bool LX200Telescope::sendScopeTime()
     struct tm ltm;
     struct tm utm;
     time_t time_epoch;
+    
+    memset(&ltm, 0, sizeof(ltm));
+    memset(&utm, 0, sizeof(utm));
 
     double offset = 0;
     if (getUTFOffset(&offset))
 
------------------------ drivers/telescope/rainbow.cpp ------------------------
index 0c68f6b39..2456f88ef 100644
@@ -1516,6 +1516,9 @@ bool Rainbow::sendScopeTime()
     struct tm ltm;
     struct tm utm;
     time_t time_epoch;
+    
+    memset(&ltm, 0, sizeof(ltm));
+    memset(&utm, 0, sizeof(utm));
 
     double offset = 0;
     if (getUTFOffset(&offset))
 
------------------------------- tools/evalINDI.c -------------------------------
index d77395033..730518f27 100644
@@ -507,6 +507,8 @@ static int pstatestr(char *state)
 static time_t timestampINDI(char *ts)
 {
     struct tm tm;
+    
+    memset(&tm, 0, sizeof(tm));
 
     if (6 == sscanf(ts, "%d-%d-%dT%d:%d:%d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec))
     {
 
2 years 1 month ago #81646

Please Log in or Create an account to join the conversation.

  • Posts: 276
  • Thank you received: 52
@Alain,

I do beleive the changes with memset are only masking an error that should be caught in the code that is building the variables ctime and cdate, see my post above. If these are correct then the code to build datetime should be passing a valid string to strptime and ltm filled in correctly.

->>>>>> snprintf(datetime, MAXINDINAME, "%sT%s", cdate, ctime);

// Now that date+time are combined, let's get tm representation of it.
->>>>>> if (strptime(datetime, "%FT%T", &ltm) == nullptr)
2 years 1 month ago #81653

Please Log in or Create an account to join the conversation.

  • Posts: 452
  • Thank you received: 71
Thanks Gene,
yes it is wise not to modify in a hurry and just digging a bigger error.
Unfortunately my time is somehow limited currently for some private reasons but I will follow the thing.
2 years 1 month ago #81656

Please Log in or Create an account to join the conversation.

  • Posts: 48
  • Thank you received: 7
@GENE, @Alain,
Thank you for your suggestion.
I thought the same as you at first.
I checked with the following debug code.
 
    LOGF_DEBUG("### OnStep ltm.tm_isdst: %i", ltm.tm_isdst);
 
    double offset = 0;
    if (getUTFOffset(&offset))
    {
        char utcStr[8] = {0};
        snprintf(utcStr, 8, "%.2f", offset);
        IUSaveText(&TimeT[1], utcStr);
    }
    else
    {
        LOG_WARN("Could not obtain UTC offset from mount!");
        return false;
    }
 
    if (getLocalTime(ctime) == false)
    {
        LOG_WARN("Could not obtain local time from mount!");
        return false;
    }
 
    if (getLocalDate(cdate) == false)
    {
        LOG_WARN("Could not obtain local date from mount!");
        return false;
    }
 
    // To ISO 8601 format in LOCAL TIME!
    char datetime[MAXINDINAME] = {0};
    snprintf(datetime, MAXINDINAME, "%sT%s", cdate, ctime);
 
    LOGF_DEBUG("### OnStep Local DateTime: %s", datetime);
 
    // Now that date+time are combined, let's get tm representation of it.
    if (strptime(datetime, "%FT%T", &ltm) == nullptr)
    {
        LOGF_WARN("Could not process mount date and time: %s", datetime);
        return false;
    }
 
    LOGF_DEBUG("### OnStep after strptime ltm date: %i-%i-%i", ltm.tm_year, ltm.tm_mon, ltm.tm_mday);
    LOGF_DEBUG("### OnStep after strptime ltm time: %i:%i:%i", ltm.tm_hour, ltm.tm_min, ltm.tm_sec);
    LOGF_DEBUG("### OnStep after strptime ltm.tm_isdst: %i", ltm.tm_isdst);
 
    // Get local time epoch in UNIX seconds
    time_epoch = mktime(&ltm);
 
    LOGF_DEBUG("OnStep Local DateTime time_epoch: %i", time_epoch);
 
    // LOCAL to UTC by subtracting offset.
    time_epoch -= static_cast<int>(offset * 3600.0);
 


The log when ltm is not initialized is as follows.
 LX200 OnStep : "[DEBUG] ### OnStep ltm.tm_isdst: 1074791425 "  <<<< wrong value
 LX200 OnStep : "[SCOPE] CMD <:GG#> "
 LX200 OnStep : "[SCOPE] RES <+09> "
 LX200 OnStep : "[SCOPE] VAL [9] "
 LX200 OnStep : "[SCOPE] CMD <:GL#> "
 LX200 OnStep : "[SCOPE] RES <04:08:07> "
 LX200 OnStep : "[SCOPE] VAL [4.13528] "
 LX200 OnStep : "[SCOPE] <getCalendarDate> "
 LX200 OnStep : "[SCOPE] CMD <:GC#> "
 LX200 OnStep : "[SCOPE] RES <03/23/22> "
 LX200 OnStep : "[DEBUG] ### OnStep Local DateTime: 2022-03-23T04:08:07 "   <<<< OnStep Local
 LX200 OnStep : "[DEBUG] ### OnStep after strptime ltm date: 122-2-23 "     <<<< OK
 LX200 OnStep : "[DEBUG] ### OnStep after strptime ltm time: 4:8:7 "        <<<< OK
 LX200 OnStep : "[DEBUG] ### OnStep after strptime ltm.tm_isdst: 1074791425 "     <<<< wrong value
 LX200 OnStep : "[DEBUG] OnStep Local DateTime time_epoch: -1 "       <<<< Error
 LX200 OnStep : "[DEBUG] Mount controller UTC Time: 1970-01-01T17:59:59 "    <<<< failed
 LX200 OnStep : "[DEBUG] Mount controller UTC Offset: -9.00 "
 Setting UTC time from device: "LX200 OnStep" "木 11 17:59:59 1970 GMT"    <<<< failed
->>>>>> snprintf(datetime, MAXINDINAME, "%sT%s", cdate, ctime);
 
 LX200 OnStep : "[DEBUG] ### OnStep Local DateTime: 2022-03-23T04:08:07 "   <<<< OnStep Local

snprintf returns the correct value "2022-03-23T04: 08: 07".

->>>>>> if (strptime(datetime, "%FT%T", &ltm) == nullptr) 
 
 LX200 OnStep : "[DEBUG] ### OnStep after strptime ltm date: 122-2-23 "     <<<< OK
 LX200 OnStep : "[DEBUG] ### OnStep after strptime ltm time: 4:8:7 "        <<<< OK
 LX200 OnStep : "[DEBUG] ### OnStep after strptime ltm.tm_isdst: 1074791425 "     <<<< wrong value
 LX200 OnStep : "[DEBUG] OnStep Local DateTime time_epoch: -1 "       <<<< Error

The date and time split by strptime is also done correctly, but time_epoch is an error (-1).
strptime doesn't seem to recalculate ltm.tm_isdst.
tm_isdst remains an uninitialized wrong value, and processing result of mktime returns an error.


When ltm is initialized, it is as follows.
 LX200 OnStep : "[DEBUG] ### OnStep ltm.tm_isdst: 0 "  <<<< initialized value
 LX200 OnStep : "[SCOPE] CMD <:GG#> "
 LX200 OnStep : "[SCOPE] RES <+09> "
 LX200 OnStep : "[SCOPE] VAL [9] "
 LX200 OnStep : "[SCOPE] CMD <:GL#> "
 LX200 OnStep : "[SCOPE] RES <04:11:37> "
 LX200 OnStep : "[SCOPE] VAL [4.19361] "
 LX200 OnStep : "[SCOPE] <getCalendarDate> "
 LX200 OnStep : "[SCOPE] CMD <:GC#> "
 LX200 OnStep : "[SCOPE] RES <03/23/22> "
 LX200 OnStep : "[DEBUG] ### OnStep Local DateTime: 2022-03-23T04:11:37 "   <<<< OnStep Local
 LX200 OnStep : "[DEBUG] ### OnStep after strptime ltm date: 122-2-23 "     <<<< OK
 LX200 OnStep : "[DEBUG] ### OnStep after strptime ltm time: 4:11:37 "      <<<< OK
 LX200 OnStep : "[DEBUG] ### OnStep after strptime ltm.tm_isdst: 0 "  <<<< initialized value
 LX200 OnStep : "[DEBUG] OnStep Local DateTime time_epoch: 1647976297 "       <<<< OK
 LX200 OnStep : "[DEBUG] Mount controller UTC Time: 2022-03-23T13:11:37 "    <<<< OK
 LX200 OnStep : "[DEBUG] Mount controller UTC Offset: -9.00 "
 Setting UTC time from device: "LX200 OnStep" "水 323 13:11:37 2022 GMT"    <<<< OK

->>>>>> snprintf(datetime, MAXINDINAME, "%sT%s", cdate, ctime);
 
 LX200 OnStep : "[DEBUG] ### OnStep Local DateTime: 2022-03-23T04:11:37 "   <<<< OnStep Local

snprintf returns the correct value "2022-03-23T04:11:37".

->>>>>> if (strptime(datetime, "%FT%T", &ltm) == nullptr) 
 
 LX200 OnStep : "[DEBUG] ### OnStep after strptime ltm date: 122-2-23 "     <<<< OK
 LX200 OnStep : "[DEBUG] ### OnStep after strptime ltm time: 4:11:37 "      <<<< OK
 LX200 OnStep : "[DEBUG] ### OnStep after strptime ltm.tm_isdst: 0 "  <<<< initialized value
 LX200 OnStep : "[DEBUG] OnStep Local DateTime time_epoch: 1647976297 "       <<<< OK
 LX200 OnStep : "[DEBUG] Mount controller UTC Time: 2022-03-23T13:11:37 "    <<<< OK

The date and time decomposition by strptime is also done correctly, and time_epoch is the correct value.

I think how mktime handles wrong tm_isdst depends on the implementation system (H / W, OS, lib, etc).
strptime manpage NOTES also describes the initialization of the tm structure.
man7.org/linux/man-pages/man3/strptime.3.html
Because of these, I think that ltm should be initialized.
You can try set the wrong value in ltm.tm_isdst.
Is there any other way to check?
The following user(s) said Thank You: Alain Zwingelstein
Last edit: 2 years 1 month ago by norikyu.
2 years 1 month ago #81657

Please Log in or Create an account to join the conversation.

  • Posts: 48
  • Thank you received: 7
sorry, my system is

INDI Server:
Raspberry Pi 4
Linux ubuntu 5.4.0-1055-raspi
indiserver 1.9.5

OnStep 4.24q

KStars 3.5.8 Stable
2 years 1 month ago #81658

Please Log in or Create an account to join the conversation.

  • Posts: 276
  • Thank you received: 52
@NORIKYU

Detective work!

But not convinced is root cause, see the code snippet below, the results I get are:
RAW ISDST = 66428
SEC = 7
MIN = 8
HR = 4
DAY = 23
MON = 2
YR = 122
DWK = 3
DYR = 81
DST = 66428
ISDST after strptime = 66428
ISDST after clobber >0 1074791425
Got MKTIME = 1648022887
ISDST after clobber =0 = 0
Got MKTIME = 1648026487 (Notice is 3600 seconds ahead of first)
ISDST after clobber < 0 -1074791425
Got MKTIME = 1648026487 (Notice is 3600 seconds ahead of first)

isdst has three states, <0, 0, >0

Could you try the below on your system?

========== code snippet =================
#include <stdio.h>
#include <time.h>
int main(void)
{
struct tm ltm;
char daybuf[20];
//char *mytime = "2022-03-23T04:11:37";
char *mytime = "2022-03-23T04:08:07";
printf("RAW ISDST = %d\n",ltm.tm_isdst);
strptime(mytime, "%FT%T", &ltm);
printf("SEC = %d\n",ltm.tm_sec); /* Seconds. [0-60] (1 leap second) */
printf("MIN = %d\n",ltm.tm_min); /* Minutes. [0-59] */
printf("HR = %d\n",ltm.tm_hour); /* Hours. [0-23] */
printf("DAY = %d\n",ltm.tm_mday); /* Day. [1-31] */
printf("MON = %d\n",ltm.tm_mon); /* Month. [0-11] */
printf("YR = %d\n",ltm.tm_year); /* Year - 1900. */
printf("DWK = %d\n",ltm.tm_wday); /* Day of week. [0-6] */
printf("DYR = %d\n",ltm.tm_yday); /* Days in year.[0-365] */
printf("DST = %d\n",ltm.tm_isdst); /* DST. [-1/0/1]*/

printf("ISDST after strptime = %d\n",ltm.tm_isdst);
//clobber isdst
ltm.tm_isdst = 1074791425;
printf("ISDST after clobber >0 %d\n",ltm.tm_isdst);
printf("Got MKTIME = %d\n",mktime(&ltm));
ltm.tm_isdst = 0;
printf("ISDST after clobber =0 = %d\n",ltm.tm_isdst);
printf("Got MKTIME = %d\n",mktime(&ltm));
ltm.tm_isdst = -1074791425;
printf("ISDST after clobber < 0 %d\n",ltm.tm_isdst);
printf("Got MKTIME = %d\n",mktime(&ltm));
}

======================================
2 years 1 month ago #81663

Please Log in or Create an account to join the conversation.

  • Posts: 48
  • Thank you received: 7
@GENE
Thank you for your advice.
I have tried your code.
RAW ISDST = -1309029128
SEC = 7
MIN = 8
HR = 4
DAY = 23
MON = 2
YR = 122
DWK = 3
DYR = 81
DST = -1309029128
ISDST after strptime = -1309029128
ISDST after clobber >0 1074791425
Got MKTIME = -1
ISDST after clobber =0 = 0
Got MKTIME = 1647976087
ISDST after clobber < 0 -1074791425
Got MKTIME = 1647976087
The time zone is Asia/Tokyo. There is no daylight saving time.
# timedatectl
               Local time: 木 2022-03-24 08:43:06 JST
           Universal time: 水 2022-03-23 23:43:06 UTC
                 RTC time: n/a
                Time zone: Asia/Tokyo (JST, +0900)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no
When tm_isdst is> 0, the result is different from yours, so I changed the time zone and tried it.
Change the time zone to US/Central, which is daylight saving time.
# sudo timedatectl set-timezone US/Central
               Local time: 水 2022-03-23 18:56:44 CDT
           Universal time: 水 2022-03-23 23:56:44 UTC
                 RTC time: n/a
                Time zone: US/Central (CDT, -0500)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no
RAW ISDST = -1615921928
SEC = 7
MIN = 8
HR = 4
DAY = 23
MON = 2
YR = 122
DWK = 3
DYR = 81
DST = -1615921928
ISDST after strptime = -1615921928
ISDST after clobber >0 1074791425
Got MKTIME = 1648026487
ISDST after clobber =0 = 0
Got MKTIME = 1648030087
ISDST after clobber < 0 -1074791425
Got MKTIME = 1648030087

It seems to be related to time zone.
You can try setting the time zone to Asia/Tokyo.
Any ideas to fix this problem?

My test system is as follows.
Raspberry Pi 4
Linux ubuntu 5.4.0-1055-raspi
GLIBC 2.31-0ubuntu9.7
gcc (Ubuntu 9.4.0-1ubuntu1~20.04) 9.4.0

Please tell me your time zone, OS, compiler, etc. you are using.
2 years 1 month ago #81672

Please Log in or Create an account to join the conversation.

  • Posts: 276
  • Thank you received: 52
@norikyu,

Yes, TZ is the key, Tokyo stopped DST in 1951 from what I can tell so passing in a positive value in tm_isdst should respond with a -1.
from man mktime
" The value specified in the tm_isdst field informs mktime() whether or not daylight
saving time (DST) is in effect for the time supplied in the tm structure: a positive value means DST
is in effect; zero means that DST is not in effect; and a negative value means that mktime() should
(use timezone information and system databases to) attempt to determine whether DST is in effect at
the specified time."

The question now may be, since this is time as read from the scope, is the scope handling the DST offset itself by way of getUTFOffset(&offset)
If yes, then isdst should be set 0 and the GMT offset used from the scope

The memset of 0 on tm does this nicely, slightly more efficient may be setting tm_isdst = 0 directly prior to calling mktime. :-)

Gene
2 years 1 month ago #81693

Please Log in or Create an account to join the conversation.

Time to create page: 1.335 seconds