React Revisited after version 16.8

React というのは DOMの内容を簡単に操作しようという JavaScriptのライブラリーの一つだが、Shadow DOMという概念を導入し、JQueryのようにコマンドごとの実行でDOMを書き換えることはせず、Shadow DOMにある程度書き込んでおいてから描画する直前にまとめてDOMに書き込む。なので軽快に動作する、というのが売り。

数年前に覚えようとしたのだが、 二点腑に落ちないところがあって、結局、Vue.jsという他のLibraryを愛用(溺愛)するに至った。

その二点というのが

1.JSXという新しい概念の導入。 一見するとHTMLなのだがHTMLではなく、XML書式をJavaScriptで理解できるようにしたプリプロセッサ。この一見HTMLというのがくせもので、class= はJSの予約用語ゆえに使えずclassName=にしなければならないなど、細かいところで違っていて気持ちがわるい。(これに比べてVueのTemplateはまごうことなきHTMLの拡張)

2.コンポーネントで操作できる変数(State)を使うためにはコンポーネントをClass表記してsetState()という関数を使って管理しなければならない。

というもの。

その後 「JSXは単なるJavaScriptの関数表現」という開発チームの解説をYoutubeでみて ストンと納得できるものがあったものの、 二つ目のJavaScriptにClassが必要というのがなんとも納得いかない(個人の意見です)身としては今いち手が出せずにいた。 Class表記をするあまり、 thisの多用を行い、しかもそのContextを明示するためにClass Constructorに this.function=this.function.bind(this) を書きまくるというのがなんとも切ない。

しかしながら、 Reactの勢いは侮りがたいものがある。 特にMicrosoftのOffice開発系の方たちは Office UI GraphicsのComponentに「Reactは正義!」という感じで使いまくっている。 SharePoinitの JavaScript Frame workも Reactびいきがすごい。

で、最近React-client-appというCLIでReactのScaffoldingが簡単にできます、という記事をよく見るので、実際どれくらい簡単なんだいと試してみたら、 生成されるScaffoldingのComponentがClass表記ではなくfunction表記になっている。 あれ、これって、Stateful Componentは Class表記しなければいけないんじゃなかったっけ、と思ったが、 実はReactも進化していた。

Version 16.8から Hooksという機能が追加されて Functional ComponentでもStateの管理ができるようになっていた。 そして今まで、 Functional Component = Stateless Component, Class Componnet=Stateful Componentとなっていたものが、 どちらを使ってもよいようになっている。 Reactのサイトにも将来の開発にはFunctional Componentを使うのがおすすめと書いてある。 なので、React-client-appもDefaultで生成するコードはクラスレスになっていたわけだ。

紹介ページ https://reactjs.org/docs/hooks-intro.html にあるコードをみれば一目瞭然だが、クラス表記のようなConstructorもなければ、this. でメンバー指定をすることもない。 非常に簡単。 ただ、このHookを使ったクラスレスのステートフルコンポーネントの作り方、オフィシャルサイト以外で解説しているサイトはまだ少ない。

この

const [ var1, setVar1]=useState('this is variable one');

で気をつけなければいけないのは Var1が複数メンバーから構成されるオブジェクトだった場合、

const [obj1,setObj1]=useState({member1:"this is member 1", member2:"this is member 2"})

のように Obj1を宣言したときに、

setObj1({member2:"this is member 2 modified"})

とやってもsetState()と違って、オブジェクトの他のメンバー(Key)とマージしてくれない。上の例ではmember1が消えてしまう。

セット関数には元のstateがパラメータとして渡されているのを利用して、

setObj1(s=>({ ...s, member2:"this is member 2 modified"}))

とスプレッド表記を使ってマージしてあげる必要がある。(上のサイトにはObject.createを使うのも可と書いてある)

また、いわゆる ComponentWillMountなどのLife Cycle hookの代わりには描画毎に発火するuseEffect()を使えと書いてある。 このHookは発火を限定するために二つ目のパラメータ―で発火する条件を指定できる。 ファイルデータを読み込むなど、あるいはイベントリスナーを設定するなど、一回だけ発火させたい場合、 このパラメーターを空のアレイで渡してあげることで実現できる。(なんとなくハックっぽいが)

useEffect(()=>{Data を読み込む云々}, [])

他にも何種類かのHooksが用意されているが、 演習用にアプリを書いてみると、上の二つのHookだけで、それなりのものができる。

すでにJSXへのアレルギーはなくなっているので、クラスを使わなくてよいReactという選択は結構魅力的です。

すべてにVue.jsを使いたいのはやまやまなれど、SharePoint関連においてMicroSoft が Reactありきの開発を推しているというのはやはり大きい。

Using Vue with WebPack

I wanted to transfer my existing script to WebPack bundle.  The application is a simple page that uses  Vue.js.   Note that I only read Introduction part of Vue and started using it.  At that time, I did not even know the concept of Vue component files .  Thus my application was entirely in one JavaScript file.

I rewrote it using typescript.   WebPack bundling was necessary to make it work.

I had to decipher minor (but important) detail on NPM’s Vue  module that should be used along with WebPack. 

If I were to use a Vue package from node_modules/ and bundle it with WebPack, then the default module that will be used is Runtime-only ES module build (vue.runtime.esm.js.)

Now this verbiage is coming from VueJs.org V2 guide
https://vuejs.org/v2/guide/installation.html#Terms


” If you need to compile templates on the client (e.g. passing a string to the template option, or mounting to an element using its in-DOM HTML as the template), you will need the compiler and thus the full build:”

This applies to ‘getting started example’ code where  you use template directly on target html file, such as 

<div id="app"> {{message}} </div>

According to Vue documentation, runtime only module is 30% lighter and when I write my code in such a way that it utilize component file (*.vue), then  using vue-loader will precompile all the templates into render function (for those within component file)  so the default settings wil be not an issue.   Issue is when I create a new instance  of the view . 
Again, according to the guide

// this requires the compiler
new Vue({
template: '{{ hi }}'
})

// this does not
new Vue({
render (h) {
return h('div', this.hi)
}
})


If I use the first method but did not configure webpack to use full version of Vue module, resulting bundle file  is missing template compiler and I will be staring at the blank page.  In this situation,  looking into  source with F12 looks something like this

<body><!-- function(a,b,c,d) {.......} --></body>


Then how do I configure Webpack  so that it knows to bundle the full version of vue module instead of runtime-only module?  It was spelled right in the guide above.

module.exports = {
          // ...
          resolve: 
                {
                   //.....,
               alias: {'vue$': 'vue/dist/vue.esm.js' }
               //.......
      }

I needed to add  ‘alias’ clause to  the ‘resolve’ section of module.exports.  (for webpack v2 and above)
WebPack will then bundle full version of Vue module(vue.esm.js). 

Since I didn’t use .vue files for this project and put everything in a single html file, I did not  need to use ‘vue-loader’ either.
So this is a minimal requirement for Vue to work with WebPack.

Vue.js has a very detailed documentation which is good. All I needed was to read it through and understand the meaning of it (lol).  

By the way, another way to make it work is not tell WebPack about Vue at all.

  1. add script tag in your HTML writeup pointing to Vue CDN
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>


    2. Then tell Typescript  that ‘Vue’ is a global object

declare let Vue:any

Yes, use the bundler but not bundle the module. It sounds strange but it works

String.replaceで知らなかった件

User がノート欄にやたら長いリンク先をそのまま張り付けて、SharePointのリストの表示が著しく損なわれるという現象が自分の管理するサイトコレクションで何件か発生している。 ユーザー教育を行ってリンクの説明を別途短文入力してください、というのは簡単だが、だまって従ってくれるような従業員ばかりではない。 そこで長いリンクを見つけたら強制的に短い文字列に置き換えてしまう、という仕掛けをJavaScriptで書いてしまえばよいのだと思いつき、 試してみた。 結果、以下のような関数を記述し、これを描画時に呼び出す形で解決した。

function shortenAnchor(text) {

    if (text===null) {
        return "";
    }
    let testPattern = /(<a.*?href=.+?>)(.*?)(<\/a?>)/g;

    function replacer(match, p1, p2, p3) {
        if((p2.length)>30) {
            p2 = p2.slice(0, 25) + '...';
        }
        return [p1, p2, p3].join('');
    }

    return text.replace(testPattern, replacer);
}

このコードで何をやっているか。 まずtestPatternを正規表現(RegExp)で記述する。 RegExpで a tag elements をグローバルにトラップする。トラップしたエレメントはタグの前の部分、中身のテキスト部分、タグの後ろの部分にグループわけされ、それぞれの文字列は$1,$2,$3として利用可能になる。( a tag element 全体のマッチは$&)。 そして、あとは String.replaceを使ってマジックをおこすわけだが、Implementationを試行錯誤している最中に 二つ目のパラメーターが実は関数でもよいのだ、というのを本日初めて知ったわけで、それを使ってうまく書くことができた。 ここに関数を使うと、以下の引数が この順番で使えるようになる。 まずは TestPatternそのもののマッチ $&, それぞれグループ分けした部分のマッチ $1,$2,$3。 よって match,p1,p2,p3として利用可能にしておく。実はこの後ろにIndexなどのパラメーターも続くのが、今回は必要がないので無視。 
この replacer という関数ではこの中身の文字列$2(p2)の長さが30文字以上あった場合、最初の25文字以下を切り捨て点三つ…を最後に追加するというもの。 この関数自体を二つ目の引数として使う。 Testしてみたら一発で完動したので感動(おやじギャグです)

普通はString.replaceというと

"this is a pen".replace("this","that") //=>"that is a pen"

という簡単な使い方は知っていたし、 最初のパラメーターを正規表現にすれば $& $1 etc., などのパラメーターを使ってかなり柔軟な置き換えなどができることも知っていて使ってはいたのだが、まさか関数まで使えるとは思っていなかった。 これは素晴らしい、と思った次第

TypeScript その2

年末の休暇を利用してtypeScriptの演習を続行中。 現在まで理解できたところをとりあえず列挙。
nodejs が導入されている必要あり。

npm install typescript -g

これで tscコマンドが使えるようになる。

tsc example.ts

そして、これでexample.ts から example.jsがトランスパイルされる。

プロジェクトフォルダー内で

 tsc init

とやると、コンパイラー設定用のtsconfig.jsonが作成され規定値が設定される。例えば、出力のJavaScriptのレベルが

<pre>”target”:”es5″</pre>

などと記述されている。またコードをトランスパイルしたときのエラーの出力設定などもできる。今のところ全く変更の必要のないレベルでトライアル中。

TypeScript は 基本的には JavaScriptのsuper setなのだが、 ’let’, ‘const’, ‘arrow function ()=>’, ‘ … spread operator’,’Template strings’ などes2015の書式が既にサポートされている。 なのでexample.tsではこれらの言語機能を使ってプログラムを書き、tscでトランスパイルすると、これらの表記をまだサポートしていない現行のブラウザでも動くようなJavaScriptに書き換えてくれる。上のConfig例ではes5レベルのコードに置き換わる。 つまりBabelと同じような使い方ができる、。

type safeなので 異なったタイプの変数へのアサインは論外としてもその可能性が生じそうなコードにはエラー表示が鬼のようにでる。例外処理とか、Interface定義を記述して対処すると満足して何も言わなくなってくれるので、バグの可能性のあるコードを書く可能性が低くなる。

TypeScript 入門

TypeScriptのイントロがDev.office.comにあるので眺めてみた。

tsとして以下の例が載っている。

class Student {
    fullName: string;
    constructor( public firstName, public middleInitial, public lastName){
        this.fullName = firstName + " "+ middleInitial + " " + lastName;
    }
}
interface Person {
    firstName: string;
    lastName : string;
}

function greeter(person: Person){
    return "Hello, "+ person.firstName + " " + person.lastName;

}

let user =new Student("Jane","G.","Doe");

document.body.innerHTML=greeter(user);

これをJSにコンパイルするとこうなる(WebStormはプラグインが動いてダイナミックに自動生成する)

var Student = (function () {
    function Student(firstName, middleInitial, lastName) {
        this.firstName = firstName;
        this.middleInitial = middleInitial;
        this.lastName = lastName;
        this.fullName = firstName + " " + middleInitial + " " + lastName;
    }
    return Student;
}());
function greeter(person) {
    return "Hello, " + person.firstName + " " + person.lastName;
}
var user = new Student("Jane", "G.", "Doe");
document.body.innerHTML = greeter(user);

うむむむむ。JSのほうがパターンに親近感があって読みやすいんですけど。でもそういうことじゃなくてTypeやクラスの定義がしっかりできて、あとあとの管理が楽、ということなんだろうな。

SharePoint Change Page Title without changing site address ページタイトルをサイトアドレスを変えずに変更する。

これってSharePointのこの部分がちゃんと動いていないだけなのではないかとおもうのだが、今現在のOffice365(SharePoint Online)のインプリメンテーションだと、Page Attributeでページタイトルを変更するとaspx ページの名前自体が変わってしまう。

たとえば https://mysite.sharepoint.com/sites/mysite/SitePages/thispage.aspx

というページがあるとして、これだと表示されるページタイトルが”thispage”となってしまう。これを Edit pageからタイトル変更して ”This Page”とすると、 サイトアドレスが

https://mysite.sharepoint.coms/sites/mysite/SitePages/This%20Page.aspx

となってしまう。サイトアドレスをなるべく短くしたいのでページタイトルとサイトアドレスの一部になるページの名前を別けることができればよいのだが、今の時点ではできない。

世の中には同じことを不便と考える人がいるわけで、何件かの記事ではSharePoint Designerを使ってマスターページを変更する方法が述べられている。すでにSharePointにある機能をターンオンするだけの簡単な修正ではあるが、

1)マスターページを変更する必要がある。
2)SharePoint Designerが必要

すなわち、サイトオーナーでかつSharePoint Designerを使えるという条件を満足していなければならない。

ブラウザーのdebug Toolで確認してみたら以外と簡単にタイトルだけ変更できることが判ったのでここに書いておく。 サイトのエディター権限があればできるというのが利点。

ターゲットのページでエディットモードに移行し、適当なところに Insert ->Embed Codeでコードエディターを開く。

以下を入力する

<script>
document.getElementById('DeltaPlaceHolderPageTitleInTitleArea').innerHTML="My Page";
</script>

これだけである。 ページタイトルが”My Page”となる。

SharePointの場合、CSRというメカニズムがあって、表示する内容の大部分は一度ブラウザーがスクリプトを実行したのち、データを描画するため、 ページへの書き込みのタイミングを遅らせなければならないのが普通だが、タイトル部分は最初の読み込み時に描かれてから変更がないため、上のようにブラウザがスクリプトを読み込んで即実行、という単純な動作でも有効なんである。

ちなみにWiki PageとWeb Part Pageの両方で有効。 Site Pageはためしていない。

 

 

constructing long string with Javascript

There is a time you need to construct a string (for instance, to create a html block) in your code.

In the simpliest approach, youcan constract the string variable  like so

var html='<head><body>’+contentVariable+’more stuff’ + ‘</body></head>’;

this becomes very messy quickly once more variables, more nested construction is needed.

I used to keep concatinating the string, like so

var html='<head></body>’;

html +=  contentVariable;

html += ‘ more Stuff’;

html += ‘</body></head>’;

 

 

Then I saw a pattern in the couple of codes from internet;

var h=[‘<head><body’];

h.push(contentVariable);

h.push(‘more Stuff’);

h.push(‘</head></body>’);

var html=h.join(”);

The More concatenation needed, the more convinient the last method becomes. Key is to join the array element with null delimiter.

Raspberry Pi でパソコン電源をInternet上から操作

家の外部からタブレットなりノートパソコンなりを使って自宅のパソコンにリモートアクセスするためのアプリというのは色々ある。Internet経由でアクセスする、というもので、Linuxでは当たり前のように実装されているし、 WindowsでもRemote Desktopというアプリケーションが同梱されているし、ファイアウオールでRemote Desktopが使えない環境でもWebベースのTeamViewer とかlogmeinというサードパーティの製品を使えばセキュアな接続がいとも簡単にできてしまう。 Chromeをブラウザとして使用しているのならChrome remote desktopというアプリが今の旬である。

 なぜそんなことが必要か、という疑問が湧くかもしれないが自分の場合、外部からお気に入りの開発環境にログインし、コード開発を一つのマシン上で行う、という使い方がメインになっている。 もちろん将来的にすべての作業がブラウザ上でできる、という環境が構築されればそんな必要はなくなるわけだが、

問題はパソコンにアクセスするには当然のことながら当該パソコンの電源が入っていなくてはならない、という事。
 エコの観点からみると年がら年中つけっぱなしになっているパソコン、というのはエネルギーの浪費に見える。 WEBサーバーを自宅のパソコンを使って構成していた時には電源をつけっぱなしにするしかなかったのだが、アイドル状態でも常に80Wくらいの消費電力が発生していた。
 現在はCubieboardという、手のひらに収まるサイズのArmcortexの開発ボードをサーバーとして使って賄っており、消費電力は3W以下だ。

で、パソコンの電源を使うときだけ遠隔操作でオンする方法がないか調べてみた。

 InstructableにElectric Impというモジュールを使って電源のオンオフをする方法が紹介されている
このモジュール、SDカードと同じform factorだが、内部にWifiモジュールとArm Coretex M3を内臓したれっきとした開発ボードであって、クラウドサービスに接続してパソコンやタブレット上から専用のコントロールパネルアプリを使って接続されたデバイスのリモートコントロールができるようになっている。

InstructableではこのElectric Impに簡単なトランジスタを追加して、PCのPower switch lineを瞬間的にショート状態にする。(つまりパソコンのスイッチを押したのと同じ状態にする)ことによってPCを起動する方法が述べられている。 Electric Impの値段は25ドル程度だが、サポート用の部品(Imp用のブレークアウトなど)を買い足すと40ドルくらいの出費になりそうだ。
自宅でcubieboardのWEBサーバーを随時動かしているのであえてアカウントを作ってクラウドを使ってコントロールする必要はないわけで、 そうすると似たようなことはArduinoでもできるはずと思うわけだが、これまたArduino本体にWifi、あるいはEthernetシールドを追加すると40ドルくらいの出費になる。 CubieBoardのGPIOをパソコンのスイッチに接続して操作することも可能だろうが、部屋が2階と地下室に分かれているし、メインサーバーになっているカードのGPIOで他のデバイスをハードウエアコントロールというのは安全性の面から心理的抵抗がある。

そこで遊び終わって引出しに眠っていたRaspberry Piを使うことにした。Desktop用のLinuxが走るほどのグラフィック性能を持つボードをただの電源スイッチとして使う、というといかにももったいない感じがするのではあるが Piの値段も含めて40ドルくらいで済んでしまうのでコストパーフォマンスの面から考えると他の方法に比べても高くはない、というか他の手間を考えるとこちらのほうが安上がりの感じ。

調べてみるとデバイス制御をPythonベースのhttp サーバーから実行できるWEBIOPIというPi用のライブラリーを発見した。 これをインストールするとGETとかPOSTのHTTP用のプロトコルを使ったRESTという手法でハードウエアのコントロールができるようになる。 つまりWEBサーバー上にページを作り、そのページ上にボタンを描画して、WEBIOPIで提供されているRESTコールを紐つけるという方法でPiのGPIOピンの遠隔操作ができるようになる。 このRESTという手法、非常に単純で、urlのパスに模してパラメーターをサーバーに送ってあげるというもの。GETはアドレスをブラウザで指定するだけで実行できるのでたとえば APIですべてのGPIOの状況を取得するAPIを使うには webiopiをバックグラウンドで走らせている状態で、

https://example.com/GPIO/*

とアドレスをブラウザに打ち込むだけで、Jason書式でGPIOの各ピンの状況が返ってくる。 ただし、これではページの表示自体がJasonのレスポンスになるので実用的ではなく、実際にはJavaScriptでコードを書くことになるが、webiopiにはうwebiopi.jsというヘルパーファイルが同梱されているので、使う難易度は低くなっている。

GPIOの使い方だが、
出力用に設定したGPIOピンをトランジスタを介してパソコンの電源スイッチとパラレルに接続し、パルス上の信号を出力してやるとパワースイッチを押したのと同様のことになり電源が立ち上がる。(電源が入っているときには逆に電源が落ちる)。電源スイッチへ接続されるピンはパソコンのマザーボード上のフロントパネルコネクター部分(パソコンケースのケーブル類を接続するコネクタ部分)に接続ピンがあるのでワイヤーをスプライスしてつなげてやればよい。。
また信号を出す前にパソコンの電源が入っているかどうかをわかっている必要があるのだが、フロントパネルコネクターには電源表示用のLEDへ接続されるピンも存在している。 そこでこのピンをGPIOでモニターすることによってパソコンに電源が入っているかどうかの判定をすることにした。

実際に組んだ回路。使ったGPIOピンは25をパワースイッチ用の出力に、24をLED電圧モニター用の入力にそれぞれ使用。 IntelのPC Interface 仕様(下に抜粋を載せます)を読む限り、パワースイッチ端子はトランジスタに直接接続(PWR+をコレクタ側に、PWR-をEmitter側に)しても大丈夫と思うが、5Vの小型リレーがたまたま手元にあったので使ってみた。NPNトランジスタのかわりに2N7000のようなFETを使えば、R1は必要ない。入力ピンのほうはLEDのVfでクランプされる電圧になるので規定の3.3V以下。万が一LEDがオープンとなっ場合5Vかかってしまうが、GPIOには保護用のクランプダイオードくらいはいっているのだろうと勝手に思い込んでいるので,保険は電流制限のR2のみ。

Table 5. Switch/LED Front Panel Electrical Connection

Pin Signal Description
2 FP PWR/SLP MSG LED pull-up (330 ohm) to +5 V
6 PWR_SW_P Power Switch high reference pull-up (10000 ohm) to +5 V
8 PWR_SW_N Power Switch Low reference pull-down (100 ohm) to GND

贅沢の極み?

贅沢の極み?


html pageの記述


<!DOCTYPE html>
<html lang="en">
<head>
<base href="https://example.com/" />
<title>PC power </title>
<!--[if IE]><script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script><![endif]-->
</head>

<body>
    <h2>Turn On Basement PC</h2>
    
パソコンの電源操作ボタンでやんす。!
<form class="buttonBar"></form>

<script type="text/javascript" src="//code.jquery.com/jquery-latest.min.js"></script>
<script type="text/javascript" src="poweronbutton.js"></script>
</body>
</html>

参照されているJavascriptの記述

/**
 * Created on 5/4/14.
 * poweronbutton.js となっているが、実際にはGPIOのモニターも行う総括的なコード
 * powerbutton element id='pb'
 * html form tag class = buttonBar.
 * GPIO #25 connected to 1n2222 which drives spdp relay to momentariry close power switch.
 * PC power switch is momentary switch.  if PC is off, it will turn on PC.  if PC is on, it will turn off pc
 * relay connected to power connections of PC system panel terminals.
 * GPIO24 connected to Power LED terminal.
 * webiopi (python httms and coap server) installed on target raspberry pi
 *
 */
function setupGPIO(){   // set GPIO25 to out for pc power switch connection.
                        // and  GPIO24 to in  for monitoring PC power LED terminal status
    $.post( 'https://example.com/GPIO/24/function/in',
        function(data) {
            if (data==='IN')setTimeout(monitorPower(),1000);
                  });
    $.post( 'https://example.com/GPIO/25/function/out',
        function(data) {
            data =(data=='OUT')?'PC Power':'setup failed';
            $('#pb').attr("value",data);

        });
}

// }
function turnon(){ // RET command to output pulse
    $.post(
        'https://example.com/GPIO/25/sequence/1000,010',
        function(data) {
            data=(data==0)?'Power switch pushed':'NG';
            $('#pb').attr("value",data); }

    );
}
function monitorPower(){//monitor GPIO 24 status every one second
    $.get('https://example.com/GPIO/24/value',
        function(data){
            data= (data==='0')?'PC is OFF':'PC is ON';
            $('#powerstatus').html(data);
    setTimeout(monitorPower(),1000); //call myself every 1second

})

}
$(function(){
    $('<input type="button" class="power" id="pb" />')
        .appendTo('.buttonBar')
        .attr("value", "Initializing")
        .attr("title", "Turn on Somethin'")
        .click(function () {
            turnon();
        });
    $('<div></div>')
        .appendTo('.buttonBar')
        .attr('id','powerstatus');
      setupGPIO();
    }
);

ターゲットのRaspberry Piにwebiopiが導入され起動されていることが前提になる。 また、上の方法では同梱されてくるwebiopi.jsは使わずに自前のJavaScriptでREST APIを直接アクセスしている。

ページの仕組み:
ブラウザーがページを読み込み終わった時点で、上のjavascriptが以下の作業を実行する。
ボタンを描画し、ボタンのラベルを”Initializing” と表示する。
GPIO25を出力ピンに設定。 ボタンのラベルを”PC Power”と書き換え、ボタンのクリック動作にパルスを送信するRESTコマンドを紐つける。
GPIO24を入力ピンに設定。同時に入力ピンの1秒ごとのモニターをスタート。WEBIOPIからRESTで返された状況に応じてページ上に”Power is ON” または ”Power is OFF”を一秒ごとに更新表示

JavaScriptの部分はRefactoringやnamespacing をやっていないので改善の余地あり。またPower LEDのモニターだけではパソコンがオンしていることはわかっても、実際にWindowsが立ち上がっているかどうかはわからないので、何らかのインターネットサービスをPi側からモニターする手法を併用するほうがよさそうだし、CSSの記述も追加してページの見栄えもよくしたいと思うが、一応初期の目的はこれにて達成。

なお、WEBIOPI自体にログイン形式のセキュリティ機能が実装されており、ページの最初のロード時にログインネームとパスワードを聞いてくる仕組みになっている。ログインとパスワードの初期値がそれぞれ”webiopi” と”raspberry” となっているので、マニュアルの手順に従って変更しておく必要がある。

また、Raspberry Piへの電源だが、パソコンの電源に5V standbyが存在しているため、ここから引き込んでいる。24p/20pコネクタの紫の線だが、マザーボードの電源側への要求スペックが500mAで電源側の仕様が2Aなので余裕のようだ。Raspberry PiもPCの筐体に入れてしまったので見た目もすっきりである。

<後記> 電力消費計を入手したので、実際のところ、どれだけエコになっているのか測定してみた。 パソコンを普通に電源投入すると80Wくらの消費になっていた。 パソコンをオフにすると7Wだ。パソコン用の電源が動いていて5Vのスタンバイ電源からPiとその他に供給しているということだ。 その差73Wだが、電気代で考えるとまったくパソコンをオンしなかった場合、年間約50ドルちょっとの節約になる。パソコンの稼働率が10パーセントくらいと仮定すると45ドルの節約なので1年でもとが取れる計算になる。

boneScriptで遊ぶ

Beagleboneblackを電子工作用にリザーブしたので、Angrstrom Linux についてくるbonescriptで遊んでみた。(Debian wheezyのイメージになっていたeMMCにAngstromの最新イメージを改めて焼き直した。) 普通javascriptといえばWEBクライエント用のプログラム言語だし、 C++やJavaなどいじっているプロの方から見るとToy Lanuguageなどとバカにされがちだけれど、自分のような日曜プログラマにとっては非常に重宝するtool なんである。 boneScriptは、このjavascriptをサーバー側で使えるようにしたnode.jsというプログラム上で走る。 BBBのハードウエアをJavaScriptの文法で操作してしまおうという優れものだ。 node.js は一般的にはwebサイトのサーバー側を能動的に管理するような形で使われるのだと思うけれど、boneScriptと組み合わせるとPC上のプログラミング言語として機能する。

JavaScriptの特徴としてプログラムの非同期実行ということがあげられる。jQueryの使い方で一度はまったことがあって、 関数によっては前に呼び出して得たreturn情報を次のステートメントで使うためにはちょっと待てという感じでプログラムの流れをブロッキングするかコールバック処理を使う必要がある。 逆に言えばコールバックを使ってのイベント処理には力を発揮する。

その特徴を使って以下のようなbonescriptをいたずら書きしてみた。BBBに実装されている4つのLEDをてんでバラバラに明滅させる、というだけのプログラム。

//#!/usr/bin/node
//uncomment the above line and chmod +x  to make it shell executable.
//This program will randomly turn on/off four on board LEDs.
// 11/28/2013
//setup()
  var b = require('bonescript');
  var LEDs=['USR0','USR1','USR2','USR3'];
  for (var i=0; i < LEDs.length;i++) b.pinMode(LEDs[i], b.OUTPUT);

//loop();
    for (var i=0;i < LEDs.length;i++) animateLED(LEDs[i]);

//helpers
function animateLED(led){
    function toggleLED(led){ //randomly toggle LED
        b.digitalWrite(led,Math.floor(Math.random()*2)?b.HIGH:b.LOW);
    }
    function randomTimer(){ //randomly set timer between 0~199msec)
        return Math.floor(Math.random()*200);
    }

    setInterval(function(){toggleLED(led);},randomTimer());
}

Arduino の流儀に従って、setup 部分と loop部分を書いてみたが、ごらんのとおり、while/until 的なloopなどしていない。 animateLED()という関数を4回呼び出したあとは、それぞれの関数インスタンスが勝手にタイミングを作って繰り返しの明滅を行っているわけで、それぞれ非同期実行されている。

ところで、
上のスクリプトはCloucd9というIDEから直接実行させる他にも、command line でも

node randomLED.js

というように、実行可能。 いちいちnode を指定するのが面倒ならば、 プログラムの一番上の行にシュバング(#!)を追加してNodeプログラムだということを明示し、

#! /usr/bin/node

randomLED.js を実行可能としておけばプログラム名を指定するだけで実行できる。

$ chmod +x rondomLED.js
$ ./randomLED.js

もともとNode.jsがPHPと同じようにサーバー側のスクリプトを実行することを目的に書かれていることを考えると、bonseScript+Node.jsだけでハードウエアをリモートコントロールできるアプリが書けそうである。