void testDateEpoch( Test * pTest) { uint32_t days = 0; uint16_t year = 0, test_year = 0; uint8_t month = 0, test_month = 0; uint8_t day = 0, test_day = 0; days = days_since_epoch(1900, 1, 1); ct_test(pTest, days == 0); days_since_epoch_into_ymd(days, &year, &month, &day); ct_test(pTest, year == 1900); ct_test(pTest, month == 1); ct_test(pTest, day == 1); for (year = 1900; year <= 2154; year++) { for (month = 1; month <= 12; month++) { for (day = 1; day <= month_days(year, month); day++) { days = days_since_epoch(year, month, day); days_since_epoch_into_ymd(days, &test_year, &test_month, &test_day); ct_test(pTest, year == test_year); ct_test(pTest, month == test_month); ct_test(pTest, day == test_day); } } } }
/** Utility to add or subtract minutes to a BACnet DateTime structure * * @param bdatetime [in] the starting date and time * @param minutes [in] number of minutes to add or subtract from the time */ void datetime_add_minutes( BACNET_DATE_TIME * bdatetime, int32_t minutes) { uint32_t bdatetime_minutes = 0; uint32_t bdatetime_days = 0; int32_t days = 0; /* convert bdatetime to seconds and days */ bdatetime_minutes = seconds_since_midnight(bdatetime->time.hour, bdatetime->time.min, bdatetime->time.sec) / 60; bdatetime_days = days_since_epoch(bdatetime->date.year, bdatetime->date.month, bdatetime->date.day); /* add */ days = minutes / (24 * 60); bdatetime_days += days; minutes -= (days * 24 * 60); bdatetime_minutes += minutes; days = bdatetime_minutes / (24 * 60); bdatetime_days += days; /* convert bdatetime from seconds and days */ seconds_since_midnight_into_hms(bdatetime_minutes * 60, &bdatetime->time.hour, &bdatetime->time.min, NULL); days_since_epoch_into_ymd(bdatetime_days, &bdatetime->date.year, &bdatetime->date.month, &bdatetime->date.day); bdatetime->date.wday = day_of_week(bdatetime->date.year, bdatetime->date.month, bdatetime->date.day); }
/* wday 1=Monday...7=Sunday */ static uint8_t day_of_week( uint16_t year, uint8_t month, uint8_t day) { return (uint8_t) ((days_since_epoch(year, month, day) % 7) + 1); }
uint32_t datetime_days_since_epoch( BACNET_DATE * bdate) { uint32_t days = 0; if (bdate) { days = days_since_epoch(bdate->year, bdate->month, bdate->day); } return days; }
/* This is your main function! You should have an infinite loop in here that * does all the important stuff your node was designed for */ int main(void) { int initialGPSLock = 1; char nmea_buf_1[NMEA_BUFFER_SIZE]; char nmea_buf_2[NMEA_BUFFER_SIZE]; char *nmea_current_buf; struct UART_buffer_descriptor nmea_buf_desc_1, nmea_buf_desc_2; gps_point cur_point; gps_speed cur_speed; sc_time_t cur_point_stamp = 0; sc_time_t last_timesync_time = 0; uint32_t gga_parse_errors = 0; uint32_t next_baro_read=0; uint32_t next_rtc_time=0; /* We allow some time for the GPS to come up before we continue here */ scandal_naive_delay(100000); setup(); scandal_naive_delay(100000); scandal_init(); scandal_delay(1000); /* Initialise the UART to the correct GPS baud rate */ #if defined(LOCOSYS) UART_Init(57600); #else #if defined(SANJOSE) UART_Init(38400); #endif #endif scandal_delay(1000); /* wait for the UART clocks to settle */ sc_time_t one_sec_timer = sc_get_timer(); /* Initialise the timer variable */ /* Set LEDs to known states */ red_led(1); yellow_led(0); // Set up the barometer long b5, pres, temp, alt, up, ut; readCalibrationValues(); //read calibration values /* Some GPS config stuff that isn't really necessary */ /* We can send a reset command if need be mtk_send_command("$PMTK103"); */ /* Set which messages to send out * This sets us to receive GPRMC and GPGGA on every position fix */ mtk_send_command("$PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0"); /* put in 5Hz mode mtk_send_command("$PMTK220,200"); */ /* Change the rate at which we fix the position. Presently every 1000ms */ mtk_send_command("$PMTK300,1000,0,0,0,0*"); /* We need a double buffer for reading the GPS messages while we parse them */ UART_init_double_buffer(&nmea_buf_desc_1, nmea_buf_1, NMEA_BUFFER_SIZE, &nmea_buf_desc_2, nmea_buf_2, NMEA_BUFFER_SIZE); /* This is the main loop, go for ever! */ while (1) { /* This checks whether there are pending requests from CAN, and sends a heartbeat message. * The heartbeat message encodes some data in the first 4 bytes of the CAN message, such as * the number of errors and the version of scandal */ handle_scandal(); if (sc_get_timer() > next_rtc_time){ ReadTime(); UART_printf("Scandal Get Timer: %d\r\n", sc_get_timer_1()); next_rtc_time+=250; } /* Read a line from the UART into one of the buffers */ nmea_current_buf = UART_readline_double_buffer(&nmea_buf_desc_1, &nmea_buf_desc_2); /* UART_readline_double_buffer will return a pointer to the current buffer. */ if (nmea_current_buf != NULL) { /* If we didn't get a valid NMEA line */ if(validate_nmea(nmea_current_buf) != 0) continue; /* check to see if we have a GGA message */ if(strncmp(nmea_current_buf, "$GPGGA", 6) == 0){ int res = parse_msg_gga(nmea_current_buf, &cur_point); if(res == 0){ if(initialGPSLock == 1) { // Syncs GPS clock with RTC SetTime(get_gga_time_array()); SetDate(get_rmc_date_array()); initialGPSLock = 0; } /*If the GPS is locked (res==0), send GPS data and set the RTC*/ toggle_yellow_led(); cur_point_stamp = scandal_get_realtime32(); scandal_send_channel_with_timestamp(CRITICAL_PRIORITY, GPSBAROMETER_FIX, 1, cur_point_stamp); scandal_send_channel_with_timestamp(CRITICAL_PRIORITY, GPSBAROMETER_TIME, cur_point.time, cur_point_stamp); scandal_send_channel_with_timestamp(CRITICAL_PRIORITY, GPSBAROMETER_LATITUDE, cur_point.lat, cur_point_stamp); scandal_send_channel_with_timestamp(CRITICAL_PRIORITY, GPSBAROMETER_LONGITUDE, cur_point.lng, cur_point_stamp); scandal_send_channel_with_timestamp(CRITICAL_PRIORITY, GPSBAROMETER_ALTITUDE, cur_point.alt, cur_point_stamp); /* Only sets the RTC if the seconds value is under 58 * This is done to make sure nothing ticks over in the * middle of a write process as strange values may result */ /* an actual parse error */ } else if (res == -1) { scandal_send_channel_with_timestamp(CRITICAL_PRIORITY, GPSBAROMETER_GGA_PARSE_ERROR_COUNT, gga_parse_errors++, cur_point_stamp); /* no fix yet */ } else if (res == -2) { scandal_send_channel_with_timestamp(CRITICAL_PRIORITY, GPSBAROMETER_FIX, 0, cur_point_stamp); //gps_lock=0; } } /* check to see if we have an RMC message */ if(strncmp(nmea_current_buf, "$GPRMC", 6) == 0) { if(parse_msg_rmc(nmea_current_buf, &cur_speed) == 0) { toggle_red_led(); /* Milliseconds since the epoch */ /* Converts date to milliseconds, adds time */ uint64_t timestamp = days_since_epoch(getRTCDay(), getRTCMonth(), getRTCYear()); timestamp *= 3600; timestamp *= 24; timestamp *= 1000; timestamp += getRTCTimeSecond() * 1000; timestamp += sc_get_timer_1(); UART_printf("Day:%d Month:%d Year:%d\r\n", getRTCDay(), getRTCMonth(), getRTCYear()); scandal_send_timesync(CRITICAL_PRIORITY, scandal_get_addr(), timestamp); scandal_set_realtime(timestamp); scandal_send_channel(CRITICAL_PRIORITY, GPSBAROMETER_SPEED, cur_speed.speed * 1000); scandal_send_channel(CRITICAL_PRIORITY, GPSBAROMETER_MILLISECONDS_TODAY, cur_speed.time); scandal_send_channel(CRITICAL_PRIORITY, GPSBAROMETER_DAYS_SINCE_EPOCH, cur_speed.date); /* This is an evil hack to make sure that we get fairly consistent timestamps Sometimes there seems to be a really long dela of ~0.3s on some timestamp messages. To get rid of this, we don't accept any time differences that are more than 20ms later than we expect them to be. This is pure evil, and the problem should really be fixed rather than hacking around it like this */ /* if(last_timesync_time == 0) last_timesync_time = sc_get_timer(); timediff = (sc_get_timer() - last_timesync_time) % 1000; if((timediff < 50) || (timediff > 600)) { last_timesync_time = sc_get_timer(); scandal_send_timesync(CRITICAL_PRIORITY, scandal_get_addr(), timestamp); } scandal_set_realtime(timestamp); scandal_send_channel(CRITICAL_PRIORITY, GPSBAROMETER_SPEED, cur_speed.speed * 1000); scandal_send_channel(CRITICAL_PRIORITY, GPSBAROMETER_MILLISECONDS_TODAY, cur_speed.time); scandal_send_channel(CRITICAL_PRIORITY, GPSBAROMETER_DAYS_SINCE_EPOCH, cur_speed.date); */ /* if(cur_point_stamp != 0){ scandal_send_channel_with_timestamp(CRITICAL_PRIORITY, GPSBAROMETER_TIME, cur_point.time, cur_point_stamp); scandal_send_channel_with_timestamp(CRITICAL_PRIORITY, GPSBAROMETER_LATITUDE, cur_point.lat, cur_point_stamp); scandal_send_channel_with_timestamp(CRITICAL_PRIORITY, GPSBAROMETER_LONGITUDE, cur_point.lng, cur_point_stamp); scandal_send_channel_with_timestamp(CRITICAL_PRIORITY, GPSBAROMETER_ALTITUDE, cur_point.alt, cur_point_stamp); cur_point_stamp = 0; } */ } } } #if 1 if (sc_get_timer() > next_baro_read){ ut = bmp085ReadUT(); //read uncompensated temperature scandal_delay(5); //delay 4.5ms up = bmp085ReadUP(); //read uncompensated pressure scandal_delay(5); //delay 4.5ms b5 = bmp085Getb5(ut); //calculate temperature constant temp = bmp085GetTemperature(ut, b5); //calculate true temperature pres = bmp085GetPressure(up, b5); //calculate true pressure alt = bmp085GetAltitude(pres); //estimate the altitude next_baro_read=(sc_get_timer()+1000); } #endif //UART_printf("B5: %d,Temp: %d:%d, Pres: %d:%d, Alt: %d\r\n", (int) b5,(int) ut, (int) temp, (int)up,(int) pres, (int) alt); // UART_printf("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\r\n",(int) barometerCal -> AC1,(int) barometerCal -> AC2,(int) barometerCal -> AC3,(int) barometerCal -> AC4,(int) barometerCal -> AC5,(int) barometerCal -> AC6,(int) barometerCal -> B1,(int) barometerCal -> B2,(int) barometerCal -> MB,(int) barometerCal -> MC,(int) barometerCal -> MD); #if 0 /* Flash an LED every second */ if(sc_get_timer() >= one_sec_timer + 1000) { toggle_red_led(); one_sec_timer = sc_get_timer(); } #endif } }