去年は原発事故を引き金に、計画停電や節電やらと大変な思いをした。
そんななか、少しでも節電意識を高めたいと、「東京電力メーター」を作って公開した。
で、今年の夏は原発再稼働の問題もあり、東電エリアだけの話ではなく、全国的に電力不足に陥りそうな感じ。これはマズい。
そんな訳で「東京電力メーター」もアプリ名に反し、関西電力、東北電力、九州電力の電力使用率も表示できるよう対応してみた。
前にも、東北電力、関西電力に対応したモノを作ったけど、その後、関西電力がcsv公開を一時止めたりしたので、今回は、関西電力を復活したり、九州電力を追加したりと、最新の公開データに合わせて修正した。
[4つの電力会社に対応]
でも何で、東京電力、関西電力、東北電力、九州電力のみの対応かというと、その他の電力会社から現状、CSVデータが公開されていないから。
あと、電力会社毎に微妙にCSVデータ形式が違うので取り込むのが大変だったりする。
でも、各電力会社からデータが公開されたら、東京電力メーターとしても前向きに実装したいと考えているので、CSVが公開されることを期待しながら待つとしよう。
[電力会社ごとのデータ公開状況]
電力会社 | 電力の使用状況 | 電力の使用状況データ | 備考 (東電仕様との主な違い) |
||
---|---|---|---|---|---|
ファイル | 1時間毎 | 5分間隔 | |||
北海道電力 | でんき予報 | CSV | ○ | × | 1時間毎のデータが公開されるようになった。 残念ながら5分間隔のデータや節電お願い文などは無い。 ピーク時供給力が時間帯(XX:00~YY:00)ではなく時台(XX:00)。 |
東北電力 | でんき予報 | CSV | ○ | ○ | 「節電お願い文」の英語版は無いが、それ以外はほぼ東電仕様。 |
東京電力 | でんき予報 | CSV | ○ | ○ | |
中部電力 | × |
× |
× |
× | 2012/3/30で終了。今後の復活に期待。 (供給力などのヘッダ名違い、翌日データ、節電お願い文、5分間隔値などが無い) |
北陸電力 | でんき予報 | × | × | × | 2012/5/6より掲載される予定。 |
中国電力 | × | × | × | × | 節電要請無しのため? |
関西電力 | でんき予報 | CSV | ○ | ○ ※3分間隔 |
東電に比べ使用率,予想気温(最低/最高),気温実績(最低/最高),翌日の使用率,予想気温(最低/最高)が追加され、逆に「節電お願い文」の英語版なし。 |
四国電力 | × | × | × | × | 節電要請無しのため? |
九州電力 | でんき予報 | CSV XML ※日毎URLが異なる |
× | ○ | 電力の使用状況データのファイル名は日付が付くので注意。 ピーク時供給力が時間帯(XX:00~YY:00)ではなく時台(XX:00)。 1時間毎のデータ、翌日データ、節電お願い文が無い。 XMLデータがあるのはGood。 |
沖縄電力 | × | × | × | × | 節電要請無しのため? |
電力会社ごとに異なるCSVフォーマットの差をプログラム側で吸収しなければならず、ゴチャゴチャになってしまったけど以下がガジェットのソースコード。
設定ダイアログ
HTMLソース:
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title>東京電力メーター</title> <meta http-equiv="Content-Style-Type" content="text/css"/> <link href="css/settings.css" rel="stylesheet" type="text/css"/> <script src="js/settings.js" type="text/javascript"></script> </head> <body> <table width="100%"> <tr> <td valign="top"> <form> <select name="gyosya" onchange="getUsageRate(this[this.selectedIndex].value);"> <option value="東京電力">東京電力 <option value="東北電力">東北電力 <option value="関西電力">関西電力 <option value="九州電力">九州電力 </select> <select name="intervalTime"> <option value="5">5分 <option value="10">10分 <option value="15">15分 <option value="30">30分 <option value="60">60分 </select> 更新 </form> </td> <td align="right" valign="top"> <font size="1"> <script type="text/javascript">document.write("Ver " + System.Gadget.version);</script><br> <a href="http://www.osadasoft.com/" target="_blank">© osadasoft</a> </font> </td> </tr> </table> <h5>電力使用状況(1時間平均)</h5> <div id="vArea" align="center"></div> <div id="linkArea" align="right"></div> </body> </html>
JavaScriptソース:
window.onload = onLoad; System.Gadget.onSettingsClosing = onSettingsClosing; img_over = new Image(10,1); img_over.src = "img/red.png"; img_out = new Image(10,1); img_out.src = "img/blue.png"; var gyosya = ""; function onSettingsClosing (event) { if (event.closeAction == event.Action.commit) { // OK ボタン System.Gadget.Settings.writeString("IntervalTime", document.getElementById('intervalTime').value); System.Gadget.Settings.writeString("GyosyaType", document.getElementById('gyosya').value); } } function onLoad(){ // 更新間隔 var idx = 0; var intervalTime = System.Gadget.Settings.readString("IntervalTime"); if(intervalTime=="") intervalTime = 15; // 初期値=15分 var max = document.getElementById('intervalTime').options.length; for(i=0;i<max;i++){ if(document.getElementById('intervalTime').options[i].value == intervalTime){ idx = i; break; } } document.getElementById('intervalTime').options[idx].selected = true; // 電力会社 gyosya = System.Gadget.Settings.readString("GyosyaType"); getUsageRate(gyosya); System.Gadget.settingsUI="settings.html"; document.getElementById('gyosya').value = gyosya; } function getUsageRate(_gyosya) { gyosya = _gyosya; var xmlHttp = new ActiveXObject("Msxml2.XMLHTTP"); switch(_gyosya){ case "東北電力": xmlHttp.open("GET", "http://setsuden.tohoku-epco.co.jp/common/demand/juyo_tohoku.csv?" + (new Date()).getTime()); document.getElementById("linkArea").innerHTML = "<font size=1><a href='http://setsuden.tohoku-epco.co.jp/graph.html'>でんき予報</a></font>"; break; case "関西電力": xmlHttp.open("GET", "http://www.kepco.co.jp/yamasou/juyo1_kansai.csv?" + (new Date()).getTime()); document.getElementById("linkArea").innerHTML = "<font size=1><a href='http://www.kepco.co.jp/setsuden/graph/index.html'>でんき予報</a></font>"; break; case "九州電力": dt = new Date(); mm=dt.getMonth()+1; dd=dt.getDate(); if(mm<10) mm="0"+mm; if(dd<10) dd="0"+dd; xmlHttp.open("GET", "http://www.kyuden.co.jp/power_usages/csv/electric_power_usage" + dt.getYear()+mm+dd + ".csv?" + (new Date()).getTime()); document.getElementById("linkArea").innerHTML = "<font size=1><a href='http://www.kyuden.co.jp/power_usages/pc.html'>でんき予報</a></font>"; break; case "東京電力": default: gyosya = "東京電力"; xmlHttp.open("GET", "http://www.tepco.co.jp/forecast/html/images/juyo-j.csv?" + (new Date()).getTime()); document.getElementById("linkArea").innerHTML = "<font size=1><a href='http://www.tepco.co.jp/forecast/index-j.html'>でんき予報</a></font>"; break; } xmlHttp.onreadystatechange = function(){ if(xmlHttp.readyState==4 && xmlHttp.status==200){ document.getElementById("vArea").innerHTML = analyzeData(xmlHttp.responseText); }else{ document.getElementById("vArea").innerHTML = "<br><br><font size='2'>読込中...</font>"; } } xmlHttp.setRequestHeader("If-Modified-Since", "Thu, 01 Jun 1970 00:00:00 GMT"); xmlHttp.send(null); } function analyzeData(_sCsv){ var sLine; var sVal="<table><tr><td valign='bottom' style='height:100px;background:white;'><p align=center>"; var cnt=0,idx=0,vPeak=0,vPeakTime="",mNo="",mComment=""; var idxHoure,idxComment; switch(gyosya){ case "九州電力": sVal += "でんき予報を参照してください。"; sVal += "</p></td></tr></table>"; return sVal; break; case "関西電力": idxHoure = 11; idxComment = 46; break; case "東北電力": idxHoure = 8; idxComment = 40; break; case "東京電力": default: idxHoure = 8; idxComment = 40; break; } while(true){ var crIdx = _sCsv.indexOf("\r\n",idx); if(crIdx!=-1){ sLine = _sCsv.substring(idx,crIdx); }else{ sLine = _sCsv.substring(idx,_sCsv.length); break; } idx = crIdx+2; if(cnt>=idxHoure && cnt<=idxHoure+23){ // 9~32行目(1時間ごとの電力) var sIdx = 0; var sDate,sTime,sToday,sYesterday; for(i=0;i<=3;i++){ var eIdx = sLine.indexOf(",",sIdx); if(eIdx==-1){ sYesterday = sLine.substring(sIdx,sLine.length); }else{ switch(i){ case 0: sDate = sLine.substring(sIdx,eIdx); break; case 1: sTime = sLine.substring(sIdx,eIdx); break; case 2: sToday = sLine.substring(sIdx,eIdx); break; } sIdx = eIdx+1; } } if(sToday=="0"){ sVal += "<img src='img/trans.png' width='10px'>"; }else{ sVal += "<img name='gImg" + cnt + "' src='img/blue.png' alt='" + sDate + " " + sTime + " " + sToday + "万kW' width='10px' height='" + (sToday/50) + "px' onMouseOver=Img_Over('gImg" + cnt + "') onMouseOut=Img_Out('gImg" + cnt + "')>"; } }else if(cnt==2){ // 3行目(ピーク) var sIdx = 0; for(i=0;i<=2;i++){ var eIdx = sLine.indexOf(",",sIdx); switch(i){ case 0: vPeak = sLine.substring(sIdx,eIdx); break; case 1: vPeakTime = sLine.substring(sIdx,eIdx); break; } sIdx = eIdx+1; } }else if(cnt==idxComment){ // 41行目(節電お願い文) var idx = sLine.indexOf(","); if(idx!=-1 && idx+1<sLine.length){ mComment = sLine.substring(idx+1,sLine.length); } } cnt++; } sVal += "</p></td></tr></table>"; if(mComment!=""){ sVal += "<h5>節電コメント</h5><font size=-3>" + mComment + "</font><br>"; } return sVal; } function Img_Over(ImgName) { if (document.images) document.images[ImgName].src = eval("img_over.src"); } function Img_Out(ImgName) { if (document.images) document.images[ImgName].src = eval("img_out.src"); }
■メーター表示
HTMLソース:
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="Pragma" content="no-cache"> <meta http-equiv="Cache-Control" content="no-cache"> <meta http-equiv="Expires" content="Thu, 01 Dec 1994 16:00:00 GMT"> <title>東京電力メーター</title> <link href="css/gadget.css" rel="stylesheet" type="text/css"/> <meta http-equiv="Content-Style-Type" content="text/css"/> <script src="js/gadget.js" type="text/javascript" charset="utf-8"></script> <body onload="run()"> <g:background src="img/background.png"> <g:image id="s" unselectable="on" src="img/needle.png" style="position:absolute;left:60px;top:0px;width:13px;height:134px;z-index:10" /> <g:image id="c" unselectable="on" src="img/center.png" style="position:absolute;left:60px;top:0px;width:12px;height:134px;z-index:11" /> <div id="vTypeArea" style="position:absolute;top:34px;left:27px;width:80px;z-index:1;font-size:xx-small;color:#888888;text-align:center;"></div> <div id="vTextArea" style="position:absolute;top:48px;left:25px;width:85px;z-index:1;font-size:xx-small;color:#AAAAAA;text-align:center;"></div> <div id="vLinkArea" style="position:absolute;top:87px;left:70px;width:50px;z-index:20;text-align:center;"></div> </body>
JavaScriptソース:
var to; var nVal=0; var vVal=0; var gyosya = ""; var intervalTime; System.Gadget.onSettingsClosed = run; function run(){ System.Gadget.settingsUI="settings.html"; s.Rotation = 180; s.addShadow("grey", 2, 40, 2, 2); clearTimeout(to); getUsageRate(); if( !isFinite( intervalTime) || intervalTime==0){ intervalTime = 15; // 数値以外または、0の場合はデフォルト値を設定 } to = setTimeout("run()",1000 * 60 * intervalTime); } function getUsageRate() { var xmlHttp = new ActiveXObject("Msxml2.XMLHTTP"); intervalTime = System.Gadget.Settings.readString("IntervalTime"); gyosya = System.Gadget.Settings.readString("GyosyaType"); switch(gyosya){ case "東北電力": xmlHttp.open("GET","http://setsuden.tohoku-epco.co.jp/common/demand/juyo_tohoku.csv?" + (new Date()).getTime()); break; case "関西電力": xmlHttp.open("GET","http://www.kepco.co.jp/yamasou/juyo1_kansai.csv?" + (new Date()).getTime()); break; case "九州電力": dt = new Date(); mm=dt.getMonth()+1; dd=dt.getDate(); if(mm<10) mm="0"+mm; if(dd<10) dd="0"+dd; xmlHttp.open("GET","http://www.kyuden.co.jp/power_usages/csv/electric_power_usage" + dt.getYear()+mm+dd + ".csv?" + (new Date()).getTime()); break; case "東京電力": default: gyosya = "東京電力"; xmlHttp.open("GET","http://www.tepco.co.jp/forecast/html/images/juyo-j.csv?" + (new Date()).getTime()); break; } xmlHttp.onreadystatechange = function(){ if(xmlHttp.readyState==4 && xmlHttp.status==200){ document.getElementById("vTypeArea").innerHTML = gyosya; document.getElementById("vTextArea").innerHTML = analyzeData(xmlHttp.responseText); document.getElementById("vLinkArea").innerHTML = "<a href='#' onclick='javascript:getUsageRate();'>" + nVal.toFixed(1) + "%</a>"; viewNeedle(); }else{ document.getElementById("vLinkArea").innerHTML = "<a href='#' onclick='javascript:getUsageRate();'>更新中</a>"; } } xmlHttp.setRequestHeader("If-Modified-Since", "Thu, 01 Jun 1970 00:00:00 GMT"); xmlHttp.send(null); } function analyzeData(_sCsv){ var sLine,sVal=""; var cnt=0,idx=0,vPeak=0,idxMinute,numOfLines; switch(gyosya){ case "関西電力": idxMinute = 49; numOfLines = 479; break; case "九州電力": idxMinute = 8; numOfLines = 287; break; case "東京電力": case "東北電力": default: idxMinute = 44; numOfLines = 287; break; } while(true){ var crIdx = _sCsv.indexOf("\r\n",idx); if(crIdx!=-1){ sLine = _sCsv.substring(idx,crIdx); }else{ sLine = _sCsv.substring(idx,_sCsv.length); break; } idx = crIdx+2; if(cnt>=idxMinute && cnt<=idxMinute + numOfLines){ var sDate = getData(sLine,1); var sTime = getData(sLine,2); var sToday = getData(sLine,3); if(sToday!="0" && sToday!=""){ nVal = (sToday/vPeak)*100; sVal = ""; if(vPeak==0){ sVal += "ピーク値取得エラー"; }else{ if(sToday==0){ sVal += "現在値取得エラー"; }else{ sVal += sTime + " 現在<br><br> " + sToday + "/" + vPeak + "万kW<br>"; } } } }else if(cnt==2){ // 3行目(ピーク) vPeak = sLine.substring(0,sLine.indexOf(",",0)); } cnt++; } if(sVal==""){ if(vPeak==0){ sVal += "ピーク値取得エラー"; }else{ sVal += "現在値取得エラー"; } } return sVal; } function viewNeedle(){ var cnt=0; if(vVal.toFixed(0)>=nVal.toFixed(0)){ for(i=vVal.toFixed(0);i>=nVal.toFixed(0);i--){ cnt++; setTimeout("setRotation(" + i + ")",20*cnt); } }else{ for(i=vVal.toFixed(0);i<=nVal.toFixed(0);i++){ cnt++; setTimeout("setRotation(" + i + ")",20*cnt); } } setTimeout("setRotation(" + nVal.toFixed(1) + ")",20*(cnt+1)); vVal = nVal; } function setRotation(_val){ s.Rotation = 2.7*_val+180; } function getData(str,tgt){ var sIdx=0,eIdx=0; for(i=0;i<tgt;i++){ eIdx = str.indexOf(",",sIdx); if(eIdx==-1){ eIdx = str.length-1; if(i == tgt - 1) eIdx++; } if(i == tgt - 1) break; sIdx = eIdx+1; } return str.substring(sIdx,eIdx); }
東京電力メーターのダウンロードはこちらから。
http://www.osadasoft.com/software/toden/
ちなみに、ガジェットファイルは「Toden.Gadget」などのように、拡張子が”Gadget”となっている。
この拡張子を”zip”に変更し、圧縮ファイルを解凍すると、そのままHTML,CSS,JavaScript,画像ファイルを見ることが出来る。