pebbleでDropboxのテキストを開く、正確な時計を表示する 単純明快な方法

[Simply.js](http://simplyjs.io/)を使う。次世代SDKの[pebble/pebblejs](https://github.com/pebble/pebblejs/)の存在には完成してから気がついた

Dropboxのテキストファイルは、認証とか面倒な事はせずに直リン可能なURLを指定する。アドウェアとか入れる必要なく、dropboxの入ったPCでテキストファイルを更新すればもうOK。
正確な時計は[nictのapi](http://www.nict.go.jp/JST/http.html) を使う。

一枚目がフリーテキスト。[cloudpebble](https://cloudpebble.net/)を使っているから日本語が豆腐になってるけど、実機では当然問題なし。スクロール可。ただもうちょいフォント小さくしたい
二枚目が時計。スマホの時計ってそもそもntpじゃなくてNITZだし、いつ補正したのかすら表示されないから全然信用出来ない。なんでデフォルトoffでいいからntp乗せてくれないの・・・上から正しい時刻、スマホの時刻、差分。リアルタイムで描画を更新してる

![imgTemp-2016-04-05-21-37-18.png](https://qiita-image-store.s3.amazonaws.com/0/5825/43aafc5f-41d9-1a8e-19ad-cc4a1552beb5.png) ![imgTemp-2016-04-05-21-38-00.png](https://qiita-image-store.s3.amazonaws.com/0/5825/1df8799e-7779-f5b6-96ff-53b4e3aeda73.png)
以下コード

```js
var formatDate = function (date, format) {
  if (!format) format = 'YYYY-MM-DD hh:mm:ss';
  format = format.replace(/YYYY/g, date.getFullYear());
  format = format.replace(/MM/g, ('0' + (date.getMonth() + 1)).slice(-2));
  format = format.replace(/DD/g, ('0' + date.getDate()).slice(-2));
  format = format.replace(/hh/g, ('0' + date.getHours()).slice(-2));
  format = format.replace(/mm/g, ('0' + date.getMinutes()).slice(-2));
  format = format.replace(/ss/g, ('0' + date.getSeconds()).slice(-2));
  format = format.replace(/yy/g, ["日","月","火","水","木","金","土"][date.getDay()]);
  return format;
};
/*
{
	id:必須
	onLoad:
	onUnLoad:
	onLongPress:
}
*/
var pages=[];
pages.push({id:"memo",onLoad:function(me){
	ajaxText("memo","https://dl.dropboxusercontent.com/s/xxx",0);
},onUnLoad:function(data){
	simply.text({body:""});
},onLongPress:function(data){
	ajaxText("memo","https://dl.dropboxusercontent.com/s/xxx",1);
}});
pages.push({id:"time",onLoad:function(me){
	var url="https://ntp-a1.nict.go.jp/cgi-bin/json?"+(new Date().getTime()/1000);
	ajax({url:url,type:'json'},function(data){
	var tickFunc=(function(){
		return function(){
			me.tick(me);
		};
	})(me)
		me.offset=data.st-data.it;
		me.timerId=setInterval(tickFunc,100);
	});
},onUnLoad:function(me){
	simply.text({subtitle:""});
	clearInterval(me.timerId);
},onLongPress:function(data){
},tick:function(me){
	var nowDate=new Date();
	var ms=nowDate.getTime()+(me.offset*1000);
	var timeObject=new Date(ms);
	var st=formatDate(timeObject,"hh:mm.ss");
	var localTime=formatDate(nowDate,"hh:mm.ss");
	simply.text({subtitle:"正:"+st+"\n誤:"+localTime+"\n差:"+ Math.round(me.offset*100)/100*-1});
},offset:0,timerId:0});

function getPageObjectFromId(pageId){
	for(var i =0;i<pages.length;i++){
		if(pages[i].id==pageId){
			return pages[i];
		}
	}
	return null;
}
function onPushCenterButton(){
	var closePage=null,openPage=null;
	var pageId=localStorage.getItem('_page')||"";
	if(pageId==""){
		closePage=null;
		openPage=pages[0];
	}else{
		var index=-1;
		for(var i =0;i<pages.length;i++){
			if(pages[i].id==pageId){
				index=i;
				break;
			}
		}
		if(index==-1){
			closePage=null;
			openPage=pages[0];
		}else{
			closePage=pages[index];
			openPage=pages[(index+1)%pages.length];
		}
	}
	if(closePage!=null){
		closePage.onUnLoad(closePage);
	}
	simply.text({body:openPage.id});
	openPage.onLoad(openPage);
	localStorage.setItem('_page',openPage.id);
}
function onPushCenterButtonLong(){
	var currentPage=null;
	var pageId=localStorage.getItem('_page')||"";
	if(pageId==""){
		currentPage=pages[0];
	}else{
		var index=-1;
		for(var i =0;i<pages.length;i++){
			if(pages[i].id==pageId){
				index=i;
				break;
			}
		}
		if(index==-1){
			currentPage=pages[0];
		}else{
			currentPage=pages[index];
		}
	}
	if(currentPage!=null){
		currentPage.onLongPress(currentPage);
	}
}
function ajaxText(localStorageKey,url,forceUpdate){
	var updateTimeSpanSecond=60;
	var nowDateObject=new Date();
	var dataUpdateUnixTime=parseInt(localStorage.getItem(localStorageKey+"-lastUpdate"))||nowDateObject.getTime();
	var dateUpdateDateObject=new Date(dataUpdateUnixTime);
	var dateUpdateString=formatDate(dateUpdateDateObject,'MM-DDyyhh:mm:ss');
	var bodyText=localStorage.getItem(localStorageKey+"-content")||"";
	simply.text({body:bodyText+"\n"+dateUpdateString});
	if( forceUpdate || updateTimeSpanSecond < (nowDateObject.getTime()-dataUpdateUnixTime) ){
		ajax({ url: url, type: 'text' }, function(data) {
			var updateDate=new Date();
			var dateUpdateString=formatDate(updateDate,'MM-DDyyhh:mm:ss');
			localStorage.setItem(localStorageKey+"-lastUpdate",updateDate.getTime());
			localStorage.setItem(localStorageKey+"-content",data);
			simply.text({body:data+"\n"+dateUpdateString});
		});
	}
}
simply.scrollable(true);
simply.on('singleClick', function(e) {
	if(e.button=="select"){
		onPushCenterButton();
	}
});
simply.on('longClick', function(e) {
	if(e.button=="select"){
		onPushCenterButtonLong();
	}
});
(function(){
	var pageId=localStorage.getItem('_page')||"";
	if(pageId==""){
		pages[0].onLoad(pages[0]);
	}else{
		var index=-1;
		for(var i =0;i<pages.length;i++){
			if(pages[i].id==pageId){
				index=i;
				break;
			}
		}
		if(index==-1){
			pages[0].onLoad(pages[0]);
		}else{
			pages[index].onLoad(pages[index]);
		}
	}
})()
```


あと、nictのurlを調べて気がついたけどレスポンスヘッダが微妙に違う。
https://ntp-a1.nict.go.jp/cgi-bin/json は

```
HTTP/1.1 200 OK
Date: Tue, 05 Apr 2016 12:42:23 GMT
Server: Apache
Access-Control-Allow-Origin: *
Cache-Control: no-cache, no-store
Content-Length: 114
Connection: close
Content-Type: application/json
```
https://ntp-b1.nict.go.jp/cgi-bin/json は

```
HTTP/1.1 200 OK
Date: Tue, 05 Apr 2016 12:42:48 GMT
Server: Apache
Access-Control-Allow-Origin: *
Cache-Control: no-cache, no-store
Content-Length: 114
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: application/json
```


ntp-b1の方はKeep-Aliveが入ってる。Simply.jsのajaxメソッドはKeep-Aliveがあるとコケるから気がついた。
Keep-Aliveがあるとコケるのも相当アレだ。