[SOLVED]Setting Yun's Date/Time

I have looked high and low for any information on how to properly set the Linino Date/Time. So far, I've tried:
date +%F -s "20140312"
(returns=2016-08-14)

date +%D -s "03122014"

(returns=03/12/16)
and even

date +%Y -s "2014"

(returns=2016). Can someone please tell me exactly what I'm doing wrong?

Edit:
I'm trying to figure out how to do this so that I can run a Process to update system time from gps every 5 minutes or so. If there is a easier way, please let me know! Also, I can't use NTP time. This yun will be outdoors far away from networks...

Stop and disable NTP server:

/etc/init.d/sysntpd stop
/etc/init.d/sysntpd disable

Change Yun back to UTC time zone.

Read UTC time from GPS:

$GPRMC,020545.600,A,3157.8299,N,03551.5057,E,18.18,37.45,130314,,,A*6C

020545.600: hhmmss.sss
130314: ddmmyy

Set date and time:

date --set "2014-03-13 02:05:45"

Thanks for the reply! I was successful in stopping, disabling and initially setting the time. My question now is, what is the best way to parse NMEA sentences and set linux time with that? I prefer TinyGPS so I was thinking of maybe declaring a variable for hour:minute:second and another for mm:dd:Y and then calling a process to set the date using those variables. Would this be a viable solution? Thanks again.

The TinyGPS examples include a print_date() function that outputs a string in a format that would work fine with the linux date command.

I don't see any other shortcuts you could do. The date command will take a wide variety of formats but chokes on ambiguous strings of numbers so some reformatting will always be necessary.

http://forum.arduino.cc/index.php?topic=208117.msg1532061#msg1532061

I prefer hook up GPS directly to linino side(no GPS shield), once it is at linux parse data is a piece of cake.
We could use Arduino to switch on/off GPS power supply for energy saver.

Biggest problem Yun did not break out any GPIO pin (total of 29). We can't directly connect GPS module to AR9331.

So i tried modifying the "simple_test" sketch from TinyGPS examples. Here is the code:

#include <SoftwareSerial.h>
#include <Bridge.h>
#include <TinyGPS.h>

/* This sample code demonstrates the normal use of a TinyGPS object.
   It requires the use of SoftwareSerial, and assumes that you have a
   4800-baud serial GPS device hooked up on pins 4(rx) and 3(tx).
*/

TinyGPS gps;
SoftwareSerial ss(9, 8);

void setup()
{
  Serial.begin(115200);
  ss.begin(9600);
  Bridge.begin();
  
  Serial.print("Simple TinyGPS library v. "); Serial.println(TinyGPS::library_version());
  Serial.println("by Mikal Hart");
  Serial.println();
}

void loop()
{
  bool newData = false;
  unsigned long chars;
  unsigned short sentences, failed;

  // For one second we parse GPS data and report some key values
  for (unsigned long start = millis(); millis() - start < 1000;)
  {
    while (ss.available())
    {
      char c = ss.read();
      // Serial.write(c); // uncomment this line if you want to see the GPS data flowing
      if (gps.encode(c)) // Did a new valid sentence come in?
        newData = true;
    }
  }

  if (newData)
  {
    float flat, flon;
    unsigned long age;
    gps.f_get_position(&flat, &flon, &age);
    Serial.print("LAT=");
    Serial.print(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flat, 6);
    Serial.print(" LON=");
    Serial.print(flon == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flon, 6);
    Serial.print(" SAT=");
    Serial.print(gps.satellites() == TinyGPS::GPS_INVALID_SATELLITES ? 0 : gps.satellites());
    Serial.print(" PREC=");
    Serial.print(gps.hdop() == TinyGPS::GPS_INVALID_HDOP ? 0 : gps.hdop());
    Serial.print(" ");
    int year;
    byte month, day, hour, minute, second, hundredths;
    gps.crack_datetime(&year, &month, &day, &hour, &minute, &second);
//    Serial.print(" "); 
//    Serial.print(month, DEC); Serial.print("/"); 
//    Serial.print(day, DEC); Serial.print("/"); Serial.print(year);
//    Serial.print(" "); 
//    Serial.print(hour, DEC); Serial.print(":"); 
//    Serial.print(minute, DEC); Serial.print(":"); Serial.println(second, DEC);
    SetTime();
  }
  
//  gps.stats(&chars, &sentences, &failed);
//  Serial.print(" CHARS=");
//  Serial.print(chars);
//  Serial.print(" SENTENCES=");
//  Serial.print(sentences);
//  Serial.print(" CSUM ERR=");
//  Serial.println(failed);
//  if (chars == 0)
//    Serial.println("** No characters received from GPS: check wiring **");
}
void SetTime() 
{
  int year;
  byte month, day, hour, minute, second, hundredths;
  gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths);
  char sz[32];
  sprintf(sz, "%02d/%02d/%02d %02d:%02d:%02d  ",
  month, day, year, hour, minute, second);
  Serial.println(sz);
  Process Set;
  Set.begin("date --set");
  Set.addParameter("year-month-day hour:minute:second");
  Set.run();  
}

No luck though. This is seriously frustrating. When I SSH into the Linino side, the "date" command returns a date from like Aug 2013. BTW, the modified part is in the function SetTime(). I'm still able to manually set the date though.

I don't have a lot of experience with addParameter, but I think you are sending the string "year-month-day hour:minute:second" rather than the variables. Have you tried
Set.addParameter(sz); instead?

Also I seem to have much more luck with runShellCommand rather than run.

I hadn't thought of that. I'll try it now.

Also I seem to have much more luck with runShellCommand rather than run.

Can you explain or show an example for me please?

Here is a code snippet from my sketch

void sendSMS(String message) {
   Process smsSend;
   String command;
   
   command = "/mnt/sd/data/sms.py 1408XXXXXXX '" + message + "'";
   smsSend.runShellCommand(command);
}

Obviously, in my code 1408XXXXXXX is a real phone number (my cell phone).

Ok i tried the runShellCommand and no joy. Here is what i tried based off of bjarne's example:

#include <SoftwareSerial.h>
#include <Bridge.h>
#include <TinyGPS.h>

/* This sample code demonstrates the normal use of a TinyGPS object.
It requires the use of SoftwareSerial, and assumes that you have a
4800-baud serial GPS device hooked up on pins 4(rx) and 3(tx).
*/

TinyGPS gps;
SoftwareSerial ss(9, 8);

void setup()
{
Serial.begin(115200);
ss.begin(9600);
Bridge.begin();

Serial.print("Simple TinyGPS library v. "); Serial.println(TinyGPS::library_version());
Serial.println("by Mikal Hart");
Serial.println();
}

void loop()
{
bool newData = false;
unsigned long chars;
unsigned short sentences, failed;

// For one second we parse GPS data and report some key values
for (unsigned long start = millis(); millis() - start < 1000;)
{
while (ss.available())
{
char c = ss.read();
// Serial.write(c); // uncomment this line if you want to see the GPS data flowing
if (gps.encode(c)) // Did a new valid sentence come in?
newData = true;
}
}

if (newData)
{
float flat, flon;
unsigned long age;
gps.f_get_position(&flat, &flon, &age);
Serial.print("LAT=");
Serial.print(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flat, 6);
Serial.print(" LON=");
Serial.print(flon == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flon, 6);
Serial.print(" SAT=");
Serial.print(gps.satellites() == TinyGPS::GPS_INVALID_SATELLITES ? 0 : gps.satellites());
Serial.print(" PREC=");
Serial.print(gps.hdop() == TinyGPS::GPS_INVALID_HDOP ? 0 : gps.hdop());
Serial.print(" ");
int year;
byte month, day, hour, minute, second, hundredths;
gps.crack_datetime(&year, &month, &day, &hour, &minute, &second);
// Serial.print(" ");
// Serial.print(month, DEC); Serial.print("/");
// Serial.print(day, DEC); Serial.print("/"); Serial.print(year);
// Serial.print(" ");
// Serial.print(hour, DEC); Serial.print(":");
// Serial.print(minute, DEC); Serial.print(":"); Serial.println(second, DEC);
SetTime();
}

// gps.stats(&chars, &sentences, &failed);
// Serial.print(" CHARS=");
// Serial.print(chars);
// Serial.print(" SENTENCES=");
// Serial.print(sentences);
// Serial.print(" CSUM ERR=");
// Serial.println(failed);
// if (chars == 0)
// Serial.println("** No characters received from GPS: check wiring **");
}
void SetTime()
{
int year;
byte month, day, hour, minute, second, hundredths;
gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths);
char sz[32];
sprintf(sz, "%02d/%02d/%02d %02d:%02d:%02d ",
month, day, year, hour, minute, second);
Serial.println(sz);
Process Set;
command = "date --set 'year-month-day hour:minute:second'";
Set.runShellCommand(command);
}

I'm at my wits end with this one. If my time isn't able to be set, this project is over.

Again I think you are send the string 'year-month-day hour:minute:second' instead of the values.
Maybe try
command = "date --set '" + year + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + second + "'";
I know pretty long, but try. And I am in a hurry so there might be typos.

OK thank you. I will try this and let everyone know the results.

bjarne:
Again I think you are send the string 'year-month-day hour:minute:second' instead of the values.
Maybe try
command = "date --set '" + year + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + second + "'";
I know pretty long, but try. And I am in a hurry so there might be typos.

OK i've tried this and here is the error I get:

simple_test.ino: In function 'void SetTime()':
simple_test:89: error: invalid operands of types 'const char*' and 'const char [2]' to binary 'operator+'

I'm also quite poor with the String type myself; you'd assuredly get a better answer in the Programming forum as this isn't specifically Yun-related. But I think what you're after is:

void SetTime()
{
  int year;
  byte month, day, hour, minute, second, hundredths;
  gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths);
  char sz[32];
  sprintf(sz, "date --set '%02d/%02d/%02d %02d:%02d:%02d'", month, day, year, hour, minute, second);
  Serial.println(sz);
  Process Set;
  Set.runShellCommand(sz);
}

You are right, I am getting the same when I try your code. Not exactly sure why, but I created the command the long way, and at least it compiles.

   command = "date --set '";
   command += year;
   command += "-";
   command += month;
   command += "-";
   command += day;
   command += " ";
   command += hour;
   command += ":";
   command += minute;
   command += ":";
   command += second;
   command += "'";
   Set.runShellCommand(command);

If this works we can always figure out what was wrong with the first way and create a little more elegant syntax.

I think what Chagrin suggests should also work, similar to what I suggested with Set.addParameter(sz)

I tried what Chagrin suggested earlier and there were no results. I'm thinking it is due to the variables being of type 'byte'. I'm done pulling my hair out over it tonight :sleeping:. I will pick up from here tomorrow. I'm thinking of converting the year, month, day, etc. variables to strings and then trying it. Thanks to all who replied today.

I played around a little tonight with the date stuff, and the following worked for me.

void setTime() 
{
   Process Set;
   String command;
   int year;
   byte month, day, hour, minute, second, hundredths;
   //gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths);
   year = 2012;
   day = 2;
   month = 9;
   hour = 18;
   minute = 5;
   second = 46;

   command = "date --set '";
   command += year;
   command += "-";
   command += month;
   command += "-";
   command += day;
   command += " ";
   command += hour;
   command += ":";
   command += minute;
   command += ":";
   command += second;
   command += "'";

   Set.runShellCommand(command);
}

Since I don't have a gps, I just set the value directly. As you can see they are still int and bytes, but the command += will automatically be re-cast as a string.
Maybe this is a place to start.

void setTime() 
{
   Process Set;
   String command;
   int year;
   byte month, day, hour, minute, second, hundredths;
   //gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths);
   year = 2012;
   day = 2;
   month = 9;
   hour = 18;
   minute = 5;
   second = 46;

   command = "date --set '";
   command += year;
   command += "-";
   command += month;
   command += "-";
   command += day;
   command += " ";
   command += hour;
   command += ":";
   command += minute;
   command += ":";
   command += second;
   command += "'";

   Set.runShellCommand(command);
}

That is definitely a step in the right direction! Thank you. You know what my next question will be, right? How can I reduce the size of this? The script I'm using is ~95% full :astonished:! But I believe I can trim some fat from it. I will try this and let you know. Thanks again bjarne!

Ok i just tried bjarne's suggestion and it works $). Thanks bjarne (+1)! The problem now is fitting it into my existing code. I will keep everyone updated on my progress.