東京電力メーターといいつつ、関西電力、東北電力、九州電力の電力使用率に対応してみた

去年は原発事故を引き金に、計画停電や節電やらと大変な思いをした。
そんななか、少しでも節電意識を高めたいと、「東京電力メーター」を作って公開した。

で、今年の夏は原発再稼働の問題もあり、東電エリアだけの話ではなく、全国的に電力不足に陥りそうな感じ。これはマズい。
そんな訳で「東京電力メーター」もアプリ名に反し、関西電力、東北電力、九州電力の電力使用率も表示できるよう対応してみた。

1
前にも、東北電力、関西電力に対応したモノを作ったけど、その後、関西電力がcsv公開を一時止めたりしたので、今回は、関西電力を復活したり、九州電力を追加したりと、最新の公開データに合わせて修正した。

[4つの電力会社に対応]
2_kansai2_kyusyu2_toden2_tohoku
でも何で、東京電力、関西電力、東北電力、九州電力のみの対応かというと、その他の電力会社から現状、CSVデータが公開されていないから。
あと、電力会社毎に微妙にCSVデータ形式が違うので取り込むのが大変だったりする。
でも、各電力会社からデータが公開されたら、東京電力メーターとしても前向きに実装したいと考えているので、CSVが公開されることを期待しながら待つとしよう。


[電力会社ごとのデータ公開状況]

電力会社 電力の使用状況 電力の使用状況データ 備考
(東電仕様との主な違い)
ファイル 1時間毎 5分間隔
北海道電力 でんき予報 CSV × 1時間毎のデータが公開されるようになった。
残念ながら5分間隔のデータや節電お願い文などは無い。
ピーク時供給力が時間帯(XX:00~YY:00)ではなく時台(XX:00)。
東北電力 でんき予報 CSV 「節電お願い文」の英語版は無いが、それ以外はほぼ東電仕様。
東京電力 でんき予報 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">&#169; 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>&nbsp;&nbsp;&nbsp;" + 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,画像ファイルを見ることが出来る。


Leave a comment

メールアドレスが公開されることはありません。

CAPTCHA


*