Sample code for the TrainInfoLib

Dependencies:   NJE10XCtrlLib NTPClient_NetServices mbed IniFileLib NextTrainFileLib TrainInfoLib lwip

TrainInfoSample.cpp

Committer:
rinosh2
Date:
2010-11-19
Revision:
1:93b052511e2c
Parent:
0:1a9fa43d77af

File content as of revision 1:93b052511e2c:

///////////////////////////////////////////////////////////////////////////////
// TrainInfo: sample code for the TrainInfo library   by rinos 2010
///////////////////////////////////////////////////////////////////////////////

#include "TrainInfo.h"
#include "NJE10XCtrl.h"
#include <time.h>

///////////////////////////////////////////////////////////////////////////////

LocalFileSystem local("local");
NJE10XCtrl gNJE(p9);

// critical section
#define TickerLock()   (NVIC_DisableIRQ(TIMER3_IRQn))
#define TickerUnlock() (NVIC_EnableIRQ (TIMER3_IRQn))

// Config file
#ifndef ROOTPATH
#define ROOTPATH	"/local/"
#endif
const char INI_FILE[]			= ROOTPATH "TInfo.ini";
const int DEFAULT_GIVEUP_SEC	= 30; // Giveup-seconds to take the next train
int  gGiveupSec = DEFAULT_GIVEUP_SEC;
char gDelayMessage[TrainInfo::MAX_DELAY_MESSAGE];
int  gDispMode = 0;
int gTimeZone = 540; // +9h00m

// Latest search cache
time_t gSerchTime;
NextTrainFile::NextInfo gNext[2];
int  gDelayStatus = 0;
const int S_INFO_OK	= 0x01;
const int S_DELAY	= 0x10;


////////////////////////////////////////////////////////////////////////////////
// LCD
#include "TextLCD.h"
void putLcd(const char* msg){
	TextLCD lcd(p24, p25, p26, p27, p28, p29, p30); // rs, rw, e, d0, d1, d2, d3
	lcd.cls();
	lcd.printf("%s", msg);
}

////////////////////////////////////////////////////////////////////////////////
// RTC Configuration

//#define USE_NTPCLIENT 1

#ifdef USE_NTPCLIENT
#include "EthernetNetIf.h"
#include "NTPClient.h"

int UpdateRTC(const char* ntp_server, int ntp_port, int timezone) {
    printf("UpdateRTC by NTPClient...\n");

	EthernetNetIf eth;
    EthernetErr ethErr = eth.setup(); // default timeout: 15sec
    if (ethErr) {
        printf("eth.setup failed %d.\n", ethErr);
        return 1;
    }
/*
	time_t now = time(0);
	if(now){
		printf("Use current RTC: %d\n", now);
		return 0;
	}
*/
    printf("Connect to the NTP server %s...\n", ntp_server);

	NTPResult ntpErr = NTPClient().setTime(Host(IpAddr(), ntp_port, ntp_server));
	if(ntpErr){
        printf("NTPClient::setTime failed %d.\n", ntpErr);
        return 2;
	}

#else
// I can't use NTPClient with LWIP HTTPClient...
// So, I get the RTC via http-NTP server.

#include "HTTPClient.h"
#define NTP2POSIX 2208988800UL

int UpdateRTC(const char* ntp_server, int ntp_port, int timezone) {
    printf("UpdateRTC by HTTP-NTP...\n");

	char rbuf[80];
    printf("Connect to the NTP server %s...\n", ntp_server);
	HTTPClient http;
	http.timeout(10);
    int len = http.get(ntp_server, rbuf, sizeof(rbuf) - 1);
	if(len){
		rbuf[len] = '\0';
		char* p = strstr(rbuf, "<BODY>");
		if(p){
			p += 7;
			time_t val = strtoul(p, 0, 10) - NTP2POSIX;
			set_time(val);
			printf("NTP set %d\n", val);
		}
    	printf("HTTPClient download [%s]\n", rbuf);
	}

#endif
	// Puts RTC (JST)
	time_t now = time(0) + timezone;
    printf("RTC(JST): %s\n", ctime(&now));
    return 0;
}

////////////////////////////////////////////////////////////////////////////////
// Display control

#include "NJE10XCtrl.h"

char gMsgNoTrain[100] = "NoTrain";
char gMsgLeft	[ 20] = "Left";
char gMsgDir	[ 20] = "To";
char gMsgSec	[ 20] = "Sec";
int  gMsgWarn = 60 * 3; // 3min

void dispTime(){
	char buf[100];
	time_t t = time(0) + gTimeZone;
	struct tm* st = localtime(&t);
	t -= gSerchTime;

	gNJE.clear();
	NextTrainFile::NextInfo* p = &gNext[0];
	if(p->m_diff < 0){
		printf("Now:%02d:%02d:%02d, %s\n", st->tm_hour, st->tm_min, st->tm_sec, gMsgNoTrain); // or error
		sprintf(buf, "%02d:%02d:%02d ", st->tm_hour, st->tm_min, st->tm_sec);
		gNJE.add(buf);
		gNJE.addAttr(NJE10XCtrl::ATTR_RED);
		gNJE.add(gMsgNoTrain);
		gNJE.setMessage(1);
		return;
	}

	// Check the difference (was gone?)
	int diff = p->m_diff - t;
	if(diff < gGiveupSec){
		p = &gNext[1];
		diff = p->m_diff - t;
	}

	// Show message to the NJE-105
	NJE10XCtrl::Attr1 a1 = NJE10XCtrl::ATTR_GREEN;
	NJE10XCtrl::Attr2 a2 = NJE10XCtrl::ATTR_SCROLL_R;
	NJE10XCtrl::Attr3 a3 = NJE10XCtrl::ATTR_NORMAL;

	if(diff < 0){
		printf("%02d:%02d Gone%2dsec ", p->m_hour, p->m_min, -diff);

		sprintf(buf, "%02d:%02d", p->m_hour, p->m_min);
		gNJE.add(buf);
		//gNJE.addAttr(NJE10XCtrl::ATTR_YELLOW, NJE10XCtrl::ATTR_SCROLL);
		gNJE.add(p->m_option);
		gNJE.add(gMsgDir);
		sprintf(buf, " Gone%ds", -diff);
		gNJE.add(buf);
	} else if(diff < 60) {
		// 123456789012345678901234 (NJE-105)
		// MM:HH •’Ê “ú‹gs Žc59•b
		printf("%02d:%02d Left%2dsec %s\n", p->m_hour, p->m_min, diff, p->m_option);

		sprintf(buf, "%02d:%02d", p->m_hour, p->m_min);
		gNJE.add(buf);
		gNJE.addAttr(NJE10XCtrl::ATTR_YELLOW, NJE10XCtrl::ATTR_SCROLL_R);
		gNJE.add(p->m_option);
		gNJE.add(gMsgDir);
		gNJE.addAttr((diff<gMsgWarn)? NJE10XCtrl::ATTR_RED : NJE10XCtrl::ATTR_GREEN, NJE10XCtrl::ATTR_SCROLL_R);
		gNJE.add(' ');
		gNJE.add(gMsgLeft);
		sprintf(buf, "%2d%s", diff, gMsgSec);
		gNJE.add(buf);
	} else {
		// 123456789012345678901234 (NJE-105)
		// MM:HH•’Ê “ú‹gs Žc01:23
		int diff_min = diff / 60;
		int diff_sec = diff % 60;
		printf("%02d:%02d Left%2d:%02d(%s)\n", p->m_hour, p->m_min, diff_min, diff_sec, p->m_option);

		sprintf(buf, "%02d:%02d", p->m_hour, p->m_min);
		gNJE.add(buf);
		gNJE.addAttr(NJE10XCtrl::ATTR_YELLOW, NJE10XCtrl::ATTR_SCROLL_R);
		gNJE.add(p->m_option);
		gNJE.add(gMsgDir);
		gNJE.addAttr((diff<gMsgWarn)? NJE10XCtrl::ATTR_RED : NJE10XCtrl::ATTR_GREEN, NJE10XCtrl::ATTR_SCROLL_R);
		gNJE.add(gMsgLeft);
		sprintf(buf, "%2d:%02d", diff_min, diff_sec);
		gNJE.add(buf);
	}

	// delay
	a1 = NJE10XCtrl::ATTR_GREEN;
	int delay = 0;
	if(gDelayStatus & S_DELAY){
		delay = 1;
		a1 = NJE10XCtrl::ATTR_RED;
	} else if(*gDelayMessage){
		if(diff % 60 < 3) delay = 1;
	}

	if(delay) gNJE.setMessage(2, gDelayMessage, a1);
	else      gNJE.delMessage(2);
	gNJE.setMessage(1, 0, a1, a2, a3);

//	if(delay) gNJE.setMessage(1, gDelayMessage);
//	else      gNJE.setMessage(1, 0, a1, a2, a3);
}

void dispDelay(){
	if(++gDispMode > 10) gDispMode = 0;
	if(gDispMode != 1){
		gNJE.delMessage(2);
		return;
	}
	printf("%s\n", gDelayMessage);
	gNJE.setMessage(2, gDelayMessage);
}

void dispWait(){
	if(++gDispMode > 10) gDispMode = 0;
	if(gDispMode != 1){
		return;
	}
	printf("Please wait...\n");
	gNJE.setMessage(1, "Please wait...");
}

void dispCB(){
//	if(gDelayStatus & S_DELAY){
//		dispDelay();
//	} else {
		if(gDelayStatus & S_INFO_OK){
			dispTime();
			gDispMode = 0;
		} else {
			dispWait();
		}
//	}
}

////////////////////////////////////////////////////////////////////////////////
// NextTrain & Delay information control
int updateNext(TrainInfo& train){
	putLcd("Update NextTrain information...");

	printf("UpdateTrain\n");

	// Next (and 2nd Next) train check
	TickerLock();
	time_t now = time(0) + gTimeZone;
	gSerchTime = now;
	struct tm* st = localtime(&now);
	for(int index = 0, offset = 0 ; index < 2; ++offset){
		NextTrainFile::Status ret = train.search(now, offset);
		switch(ret){
		case NextTrainFile::S_SUCCESS:
			if(train.next()->m_diff > gGiveupSec){
				gNext[index++] = *train.next();
			}
			break;

		case NextTrainFile::S_NO_TRAIN:
			gNext[index++].m_diff = -1;
			break;

		default:
			gNext[index++].m_diff = -2;
			break;
		}
	}
	gDelayStatus |= S_INFO_OK;
	TickerUnlock();
	return 0;
}

int updateDelay(TrainInfo& train){
	putLcd("Update Delay Information...");

	// Delay check
	TrainInfo::Status ret = train.checkDelay();
	if(ret == TrainInfo::S_DELAY_DETECTED){
		TickerLock();
		train.getDelayMessage(gDelayMessage, sizeof(gDelayMessage));
		gDelayStatus |= S_DELAY;
		TickerUnlock();
	} else {
		TickerLock();
		train.getDelayMessage(gDelayMessage, sizeof(gDelayMessage)); // copy for testing...
		gDelayStatus &= ~S_DELAY;
		TickerUnlock();
	}
	return 0;
}

int updateAll(){
	TrainInfo train;

	if(train.open(INI_FILE)){
		printf("Can't open INI file '%s'\n", INI_FILE);
		return 1;
	}
	updateNext (train);
	updateDelay(train);
	return 0;
}

////////////////////////////////////////////////////////////////////////////////
// Configuration and Startup
int setupParams(const char* inifile){
	char ntpserver[100] = "ntp.jst.mfeed.ad.jp";
	int ntpport  = 123;

	const IniFile::IniList INI_PARAM_LIST[] = {
		INIFILE_INT("GiveupSec", gGiveupSec),
		INIFILE_STR("NTPServer", ntpserver, sizeof(ntpserver)),
		INIFILE_INT("NTPPort",   ntpport),
		INIFILE_INT("TimeZone",  gTimeZone),

		INIFILE_STR("MsgNoTrain",	gMsgNoTrain,	sizeof(gMsgNoTrain)),
		INIFILE_STR("MsgLeft",		gMsgLeft,		sizeof(gMsgLeft)),
		INIFILE_STR("MsgDir",		gMsgDir,		sizeof(gMsgDir)),
		INIFILE_STR("MsgSec",		gMsgSec,		sizeof(gMsgSec)),
		
		INIFILE_INT("MsgWarn",		gMsgWarn),

		INIFILE_END,
	};

	IniFile::getval(inifile, INI_PARAM_LIST);
	gTimeZone *= 60;

	// Init NJE
	gNJE.setScrollSpeed(NJE10XCtrl::ScrollSpeed(NJE10XCtrl::SCROLL_FAST));
    //gNJE.setBlinkSpeed(NJE10XCtrl::BlinkSpeed(NJE10XCtrl::BLINK_FAST));
    gNJE.setStopTime(1);
	gNJE.setMessage(1, "Please wait...");


	// Init RTC	
	putLcd("Connect to the NTP server...");
	UpdateRTC(ntpserver, ntpport, gTimeZone);
	return 0;
}

int main(){
	putLcd("Start TrainInfo!");
	
	setupParams(INI_FILE);
	Ticker dispTicker;
	dispTicker.attach(dispCB, 1); // 1 update per sec

	for(;;){
		printf("Update information\n");
		if(updateAll()) break;

		// Free LocalFileSystem before waiting.
		// (For access file via USB)
		putLcd("Wait for the next update event");
		wait(60);
	}
	dispTicker.detach();
	printf("Program end\n");
	return 0;
}