HP‐12Cのセグメント欠け

自分の持っているHP-12Cは電池がCR2032を2枚使うもので、要はオリジナルではなく、21世紀に入ってから作られたAtmelのマイコンを使ってオリジナルのファームウエアをエミュレートしたものだ。 当然実行速度は速くなっており、形状的にも手軽なのでちょっとしたビジネス計算用にオフィスの机の上に置いてあったのだが、使いだしてから半年もたたないうちにLCDのセグメント欠けが発生するようになった。セグメントが1本、2本とかけていくもので8を表示しようとすると日の代わりにトのような表示になってしまう。 最初は電池を変えるともとに戻ったりしていたのだが、そのうち欠けるセグメントがどんどん増えてきて計算機として用をなさなくなってしまった。

というわけで卓上には48Gを復活させ、12Cのほうは机の引出に投げ込んであった。

最近、整理をした時に出てきたので、どうせ捨てるならその前にばらして中身を見てみよう、と思った。

ゴム足の下のネジ4本と電池室のネジ2本を外すと、上蓋と下蓋に分解できる。 この状態で観てみると、表示用のLCDのFPCの端面が部品実装した配線板に直接張り付けられている。 経験上からHeat Sealという製法で接着されているとわかったので、この状態で電池を入れ、試しにFPCのこの部分をピンセットの先で配線板に押し付けてみると、一部の表示が復活する。押す場所によって復活するセグメントの位置も変わる。

工程上では加熱圧着することによって接続をとることになっているが、接続部分がはがれかかっているらしい。 そこで 小型のHeat Gunを使ってこの部分を温めながら、マイナスドライバーの先で、FPCの接続部分をまんべんなく押してみた。

さめるのを待って電源ONしてみたらセグメント欠けは無くなっており、通常作動に戻っている。

組み立てなおしてHP12Cしっかり復活してしまった。 2か月ほど経過したが問題なし。

近頃のHPの電卓は品質管理が良くないね。

SparkFun.com’s dumpster dive

Sparkfun’s dumpster dive is once in a few months event when they prep a limited amount of red boxes filled with rejects and some left over that they don’t feel as retail quality merchandize for various reasons, and put them on sale.

I bought these boxes on two occasions so far and I am reasonably pleased.
Let me share my experience.

  • Sale.
  • The sale takes place on select Fridays. In both occasions I learned about the sale when I visited the site to check out their blog section for new products, which they announce on every Friday morning.
  • The sale event will occur at 12 noon MT.
  • The whole lot will only last a couple of minutes, then the sale will be over.
  • Prior to Noon, you go to the site, login and go to the product page(DD-12012). There is no purchase button displayed yet. Precisely at 12 Noon, you start hitting the F5 key to refresh the screen. Once you see the Buy button, click on it to secure your purchase. If you can go through the purchase process in less than 2 minutes (confirming your address, shipping method and payment information and so so on – the fact you are already logged in will help expedite the process), chances are you will be rewarded with the order confirmation page.
  • Wait with a great anticipation for 3~4 days for the box to arrive.
  • Open the box and find out what is in there.
  • First purchase. (Feb 2014) – All parts listed were confirmed functional.
    • Pcduino v1 x1
    • PIC KIT2 compatible CANAKIT programmer x1
    • Vehicle diagnostic kit x1
    • Sonar module x2
    • FTDI USB-Serial converter (3.3V) x1
    • Stepper motor driver board array. I was able to separate 5 good boards while destroying 1 using dremel
    • A lot of electrolic capacitors
    • One comparator, One photo interrupter, One gap sensor, One ADC.
    • Half dozen of banana plugs
    • USB bluetooth dongles.
    • 3 pin rotary encoder x1
  • Second purchase
    • LCD module 24 chars x 2 lines
      It had 14pin connector. Using Arduino example sketch and pin out information I gathered from Internet, The module was confirmed functional. There is a two terminal pad on PCB which is obviously for backlighting and it looks like EL lighting. $10 value.
    • LCD module 16 chars x 2 lines
      There was a 14 pin ribbon cable coming out from the module. Again I used the pinout and Arduino Uno to confirm the functionality but this one did not work at the first time. It turned out the ribbon cable was broken, so I removed it and replaced with a header connector. The part is now working. $7 value.
    • Bleep drum version 1
      1) This assembly was in a bad shape. I suppose the kit was used in a class room environment or something, but who ever built the kit got the switch and stereo plug on the wrong side of the PCB and must have abondned the project. 9V battery holder and one of four studs were missing as well. Desoldering those multiple lead components was not a fun at all.
      2) I attached 9V battery and powered it up, hoping the LED will light up. Nothing happened and 78I05 was getting rather hot. Quick check on the output of the voltage regulator indicated something was loading down the VR really bad. Pop out the 8 pin dip and LED started to respond to button pushes. VR out was 5V. Oh, bad IC chip I thought and looked a t the part number on it. This is where real shocker camein. It said TA7015D, which is audio Amplifier. Wait a minute, the schematic I found on the Internet says this should be 4901 DAC! Both are 8 pin DIP IC but was the kit supplied with the wrong IC chip?
      3) So I replaced a chip with 4901. I purchased it from mouser.com when I ordered other parts. Now it seems to be working $50 value?
      4) If the kit was supplied with a wrong chip, then the poor guy who attempted to build it had no chance of this working.
      5) I also feel bad for people who is coming to electronic kit building these days. In my days, components were large. Solder pads were large and solder melting temperature was low due to lead in the solder. It is more difficult to work on PCB soldering even for me who I consider somewhat experienced in soldering.
      6) Bleep Drum is fun!
    • LPC 1768-H blue board
      1) This is a retired Arm cortex board on Sparkfun site. NGX saite is still selling it for $50 or so.
      2) When powered, the test LED was dim and there was no initial booting action where the LED was supposed to blink four times. Scoping the LED output confirmed it was blinking too fast. Somebody must have tried to download a blinky program but with a wrong timer value.
      3) I tried to connect to UART0 with USB-serial cable (using just black-GND, Green-RX0, White-TX0, no connection to red wire) connection after downloading flashmagic. Rebooting while sw press started a bootloader and I was connected. I reinstalled USB secondary bootloader.
      4) Now the USB bootloader started to work. I was able to drag and drop the initial bin file to the board. The board is now reinstated to its original shape. When powered up, LED blinks four times and wait to be programmed.
      5) But I don’t think I keep looking at this board because these days there are so many other options to jump into Arm micro controller more cheaply and easily . I am experimenting with FRDM-KL-25Z with mbed tool chain and its incredibly easy to use. Cypress PSoC now sells $4 board that comes with USB serial interface that can be snapped off for dedicated USB-UART cable afterwards. What a world are we living in?
    • Atmega 328P DIP
      1) Pins were all mangled up so I need to straighten them using a pair of tweezers. Popped into ISP programmer that I hacked with Arduino nano but AVRdude can not read the content. Its either a)broken, b)fuse is configured so can not be programmed without paralell programmer or c)fuse is set to use external crystal.
      2) Out of whim, I popped out the 328p from Arduino uno that I had and placed the 328p in question into Arduino board, loaded the blinky program and on-board LED started to blink. So this must be a 328p with arduino bootloader preloaded. $6 value.
    • More Atmega micro controllers (4 of them)Those are all SMT components. I probably would not be able to use them
    • SC300 wifi module x5
      This looks fantastic but I don’t know how I can use them in this SMT pinouts.
    • Header pins.I received about two dozens of solid header pins. It turns out a perfect fit for my NRI (National Radio Institute) Lab Trainer’s terminal pins which were too loose to connect jumper pins to. So I broke up these header pins to single pins and soldered on top of terminall pins on my trainer. Now the jumper wires slide into it very snuggly. The 35 years old electronics lab trainer regained a new life. Nice.

Will I try the dumpstar again? Maybe I will. The process of troubleshooting seemingly non-working product has some attraction in it.

ハノイの塔を解く(Solving Towers of Hanoi)

ハノイの塔というのはパズルだが、リカージョンというアルゴリズムによくなじむのでプログラミングの教科書に出ていることがある。 自分がこれを見たのは”Oh Pascal!”というパスカルの入門書で30年くらい前に発行された学生向けの教科書だ。
パズルの内容はこんな具合。
1.3本の棒が立っている。仮にこれを右からA,B,Cとする。
2.Aには真ん中に穴のあいた円盤が積み上げてある。円盤の直径は底にあるものが一番大きく、上に行くほど小さくなる。
3.一度に一個ずつこのこの円盤を取り出して他の棒に移すことができる。最終的には全部の円盤をCに移したい。
4.ただし、大きな円盤を小さな円盤の上に置くことはできない。

Hanoiの塔というのはこの”金の”円盤を64枚積み上げたものだそうで、このパズルが解けたときには世の中が終焉を迎える、というオトロしい落ちがついている。

これをコンピュータープログラムを使って解くとどうなるか、という話である。 パターンを見つけるために少ない枚数で実際に解くことを試みる。
Disk(円盤)の数が一枚の時には簡単だ。円盤をAからCに移せばよい。

Move(1disk from A to C) = Move a Disk from A to C

では2枚の時にはどうなるか

Move(2disks from A to C) = 
 Move a Disk from A to B
 Move a Disk from A to C
 Move a Disk from B to C

ここで棒Bを使うことになる。 つまり、まず上の円盤を棒AからBに移し、下の円盤をAからCへ、最後にBに移してあった円盤をCに移して完成だ。

Move (2 disks from A to C) = Move (2 disks from A to C using B)

3枚はどうか。 すでに2枚を動かす方法はわかっているのその方法を使ってまずは2枚をBに動かしておき、最後の一枚をAからCに移動、さらに2枚を動かす方法を使ってBからCに移動するという方法で動かせる。

Move(3 disks from A to C using B) =
 Move(2 disks from A to B using C)
 Move a disk from A to C
 Move (2 disks from B to c using A)

4枚の場合も同様に考えられるのでパターンとしては (n-1)枚の円盤をAからBに移す。最後の円盤をAからCに移動し、その後(n-1)枚の円盤をBからCに移す。 ということになる。

Move (n disks from A to C using B) =
 if n>2 Move (n-1 disks from A to B using C)
 Move a disk from A to C
 if n>2 Move (n-1 disks from B to C using A)

このパタ-ンを使って関数を書くと、自分で自分自身を呼びだす関数になる。これがいわゆるRecursion と呼ばれるプログラムテクニックだがCでもPascalでもPHPでもいまどきのプログラムなら軒並みサポートされている。ただし普通のループに比べるとスタックにどんどん自分のコピーを積んでいくためメモリーを消費し、昔の8ビットパソコンでは何せRAMが32キロバイトあれば高級機、計算しているうちにメモリーが足りなくなる、なんてこともあったりして、Loopで記述できるものはRecursionをさける、というのが常識だった。
しかしながらこの記述の簡便さ、短さは感動ものである。今のパソコンはそんなにメモリを気にしなくてもよいので、改めて組んでみよう。
上のパターンは条件判定を何度も呼ぶことになるので少し工夫して

function Move (n, from, to , using) =
 if n=1 "Move a Disk from 'from' to 'to'"
else
 Move (n-1,from, using,to)
 "Move a Disk from 'from' to 'to'"
 Move (n-1,using, to, from)

というようなロジックを使うこととし、
Free Pascalで書いた例

program hanoi;
             {Recursively solve the towers of Hanoi problem.  Moves disks from A to C.
             The code from "Oh Pascal" by Doug Cooper}
var height:integer;
  procedure Move (Height: integer; FromPeg,ToPeg,UsingPeg:char);
  begin
    if Height = 1
    then writeln('Move disk from ', FromPeg,' to ',ToPeg)
    else begin
      Move (Height-1, FromPeg,UsingPeg,ToPeg);
      writeln('Move a disk from ',FromPeg,' to ',ToPeg);
      Move (Height-1,UsingPeg,ToPeg,FromPeg)
    end;
  end;

begin
  writeln('How Many disks are you going to start with?');
  readln(Height);
  Move (Height,'A','C','B');
  readln()
end.

C++で書いた例

#include < iostream >

using namespace std;
void move(int numberOfDisk, char fromPin,char toPin,char usePin);


int main() {
    int numberOfDisk;
    char fromPin = 'A',usePin='B',toPin='C';
    cout << "How many disk do you want to move from pin A to pin C?: " ;
    cin >> numberOfDisk;
    move (numberOfDisk,fromPin,toPin,usePin);

    return 0;
}
void move(int numberOfDisk, char fromPin,char toPin,char usePin) {
    if(numberOfDisk == 1) cout << "Move a Disk from "<< fromPin << " to " << toPin<< endl;
    else {
        move(numberOfDisk-1,fromPin,usePin,toPin);
        cout << "Move a Disk from " << fromPin << " to " << toPin << endl;
        move(numberOfDisk-1,usePin,toPin,fromPin);
    }

}

Pythonで書いた例

'''Towers of Hanoi'''
def move(numberOfDisk, fromPin, toPin, usingPin):
    if (numberOfDisk == 1):
        print ("Move a Disk from ",fromPin," to ",toPin)
    else:
        move(numberOfDisk-1,fromPin,usingPin,toPin)
        print ("Move a Disk from ",fromPin," to ",toPin)
        move(numberOfDisk-1,usingPin,toPin,fromPin)

if __name__ == '__main__':
    numberOfDisk = input("How many Disk would you like to move? ")
    move(int(numberOfDisk),'A','B','C')


Python で円盤の数を4とした場合の実行例


~ $ python3 hanoi.py
How many Disk would you like to move? 4
Move a Disk from  A  to  C
Move a Disk from  A  to  B
Move a Disk from  C  to  B
Move a Disk from  A  to  C
Move a Disk from  B  to  A
Move a Disk from  B  to  C
Move a Disk from  A  to  C
Move a Disk from  A  to  B
Move a Disk from  C  to  B
Move a Disk from  C  to  A
Move a Disk from  B  to  A
Move a Disk from  C  to  B
Move a Disk from  A  to  C
Move a Disk from  A  to  B
Move a Disk from  C  to  B

動かす回数は円盤の数が1の時は1、2の時は3、3の時は7、4の時は上の出力のように15となり、円盤の数がnのときは

2のn乗から1を引いた値

となる。枚数が多ければ多いほど全部のステップの数がどんどん大きくなっていく。
Python version で試してみると、手持ちのややくたびれたノートブックパソコンではステップの出力が終わるのに 円盤の数が23枚で30秒、24枚で1分、25枚で2分かかった。(下の出力結果参照)実行時間がここの調子で倍々で増えていくとすると入力が64枚のときに解法を出力するのに2の38乗の分がかかるということになるが、これを年に直すと、なんと52万年というとんでもない数字になる。 ので上のプログラムに64と入力しようものなら計算が終わらない。 なるほど、これでは世界が滅びるわけだ。

~ $ time echo 23 | python3 hanoi.py >/dev/null
real	0m29.308s
user	0m29.225s
sys	0m0.054s
~ $ time echo 24 | python3 hanoi.py>/dev/null
real	0m58.437s
user	0m58.237s
sys	0m0.122s
~ $ time echo 25 | python3 hanoi.py>/dev/null
real	1m55.068s
user	1m54.540s
sys	0m0.320s

Hiding SharePoint list column from list view

This article is about a javascript snippet that hides a specific column from a SharePoint list view. If I google this subject, most of the articles found on the Internet is about hiding a specific column from new, display or edit form. Although javascript can do this, you can do the same thing without use of javascript by enabling list content-type as well. See here.

Not many articles talks about hiding columns from the list view though. (This one is an exception)
The link above shows the solution for toggling the particular columns. I only needed to hide a column from the list. But why do I even want to do that when one can simply create a view without that specific column you don’t want to see?
The reason is that I want to show the list based on filtered value from the column in question. I can add the filter webpart that I can connect to the target list, then specify the column to which the filter webpart will be connected to. In another word, for the filter to work, the column need to be a part of the list view (This is no longer the case with SharePoint 2013 or SharePoint online.  See below). Since the column will always show the same value for all displayed items(filtered value) I want to hide this column. If your company allows the use of SharePoint Designer, then you can use the Dataview webpart where you can use the column that is not shown to filter the items list. But Dataview creation and editing requires SPD. I wanted a easier solution, hence this javascript snippet.

if (typeof jQuery === 'undefined') { throw new Error('hide column snippet requires jQuery') }

//This function gets targetTable object and columnindex to hide
//targetTable is a jQuery object with single element.
function doHideColumn(targetTable,col) {
    targetTable.find(".ms-viewheadertr >*[class^='ms-v']").eq(col).hide();
    targetTable.find(" >tbody >tr").each(function(){$(this).find(">td:eq("+col+")").hide();});
}
$(function() {//this hide the colName column from all table in the page
    var    colName="colToHide";
    var    tarray=$("tr.ms-viewheadertr th:contains('"+ colName +"')");
    var    tlength=tarray.length;
    var    colindex;
    for (var i=0; i<tlength; i++) {
        colindex=$(tarray[i])[0].cellIndex;
        doHideColumn($(tarray[i]).closest('.ms-listviewtable'), colindex);
    }
});

 


This code snippet requires jQuery. You can use content editor Web Parts (CEWP) to include this code (don’t forget to wrap the code with script tag.) It works with SP2007 (My office’s current version) I may need to look at the code again when our IT upgrades the server to either 2013 or O365.  *Edit*  On SharePoint 2013 and SharePoint online filter can be applied to any list column regardless of if the target liist view contains the filtered column.  Therefore, solution explained here is unnecessary. *end Edit *
The code above scans the entire page for column headers with “colToHide” name and hide the column. (or columns if there are multiple lists in the page and if they contains the column with same name)
Since this code uses jQuery array object to hold the column information, it wont be difficult to modify the code to accept more than one column names to hide multiple columns from single list. For now, this snippet achieves what I need.

Filter Web parts are nice. For instance, URL query web parts let me create a page that contents are based on the filtered value in url query. For instance,
http://projectpage.aspx?projphase=1
http://projectpage.aspx?projphase=3
both link goes to the same page but the first link will show project phase 1 list items where the next link will show project phase 3 list.

Android 4.2以降(Nexus 7,Samsung Galaxy etc.,)のUSB Debugモードを有効にする方法

ようするにFirst Generation Nexus 7のUSB Debuggingを有効にするにはどうしたらよいのか、という問題。

従来のAndroid Devciceはセッティングに行ってDevelopper Optionsを選び、その中のUSB DebuggingをOnにすれば事足りるのだが、なんとNexus7ではこのDevelopper Options自体が存在しない。

そんな馬鹿な、とググってみたところ、StackOverflowに以下の記述があった。

SettingのAboutを選択し、Build Numberの欄を7回タップする。

Voodooじみているが、これで Developper OptionがSetting Menuに出現する。

4.2のデバイスってみんなそうかしらん。
と思って手持ちのGalaxy S3(firmware 4.4.2)を眺めてみれば、 おんなじじゃん。 知らなかったのは私ばかりなり。
Easter Egg のノリだね。

Sprint: your account can not be validated [Solved]

I got this recorded message when I swapped my cell phone from Samsung Victory to Galaxy S3 and tried to call somebody.

The S3 used to belong to my son, but he upgraded it to HTC One. which left the S3 unused. The phone is more capable than Samsung Victory that I was using, so I decided to swap the phone.
The process couldn’t be easier. After hard resetting and wiping my son’s setup including gazillion of text chat history, It can be done online by logging into sprint.com and select “upgrade my phone” menu selection from my device page. Sprint.com site is clever enough to recognize that I have unused Galaxy S3 under my account and suggested the device as a target device for the swap. It was just the matter of following the step by step instructions on the site page.

So the swapping was done in no time without pain, or so that I thought.

After the swap process, the phone was recognizing network. Setting up Outlook mail service, Google service and Dropbox service was completed without any issue. All I needed to know were the user name and password. Then the phone was receiving e-mails.

I could not call from the phone however. When I tried to call the phone from the land line and got the voice mail message. Also, when I tried to turn on the hotspot, I was told I was not subscribed to the service (which I am)

I first try to call Sprint but I was on hold for 20 minutes. during that time I was googling the net and found several posts regarding this problem. Most of the responses, including the ones from sprint support team was not helpful at all. Then I stumbled accross this one. This one turned out to be the right answer.

The process to remedy this problem, turned out to be simple. you need to go to “Settings” -> “More” ->”System Update” then select “Update Profile”.
The phone will want to reset itself once the update is complete, and after the reset, everything started to work.
I suspect, there was still some of my son’s profile data remained on S3 and it confused the network connection.
Now I have a cell phone with bigger size screen and bigger size memory. Considering the fact that my wife carries S4 and my son HTC one M8, I am lagging in the technology but hey, I am perfectly happy with what I got for free.

SSDに換装したWindows7 AHCI モードでクラッシュ

一世代前のノートブックパソコン、まだまだ使えるのだが、動作がやや緩慢、そこで最近ぐっと購入しやすい値段になってきたSSDに換装してみた。 使ったのは250GBのSamsung840EVo。
Windows用のマイグレーションソフトウエアが付属してくるのでUSBを通してSATAに接続できるケースさえ手元にあればディスクイメージのコピーは問題なくできる。 あとはパソコンの裏ケースをはずし、HDDを取り出して、SSDを組み付けるだけ。ただし、Dual Bootで入れておいたMint Linuxはきれいに無視されるので、バックアップとリストアをしっかりおこなっておいて、再導入する必要があった。またWindowsのリカバリーパティションも複製されないようなので、リカバリーディスクを作成しておく必要がありそうだ。
Windows7の起動とアプリケーションの起動が圧倒的に早くなった。 めでたしめでたし、と思ったが、付属のSamsung Magicianという管理ツールを使ってみると、AHCIモードが無効になっているので、最適状態ではない、というようなメッセージが出ている。
AHCIというのはディスクの管理モードのようで、BIOS画面を見るとHDDのアクセス方法の選択肢の一つになっていた。 このパソコンの規定値はIDEアクセスモードになっており、これをAHCIに変えてやればよいと思ったのだが、設定を切り替えて作動させてみるとWindowsが起動途中でクラッシュする。いわゆるBSOD(Blue Screen of Death=青いエラー画面)が出てその内容を読む暇もなくリセットがかかる。

しょうがないので、Bios設定を元にもどし、再起動。 Google検索で”BSOD Windows 7 AHCI SSD”のキーワードで検索したら、 以下の記事を発見。なんと4ねんん以上も前に書かれている。こういうEarly Adapterがいてくれるおかげで後からついていく我々はネット検索するだけで問題解決ができてしまう。

HKEY_LOCAL_MACHINE / SYSTEM / CurrentControlset / Services /msahci
このレジストリの値を0に変更(自分の場合は3になっていた)してWindowsを終了し起動の途中でF2キー(Deleteキーの場合もある)を押してBios画面を呼び出して AHCIに設定しWindows7を起動すると今度はクラッシュすることなく必要なドライバーを導入した後、再起動を促されるのでもう一度リブートして解決。

Python、comprehension を使った一括処理

Pythonには” … for … in”という構文を使った、一括でメンバー要素を処理する機能がある。Comprehensionと呼ばれ、リスト、セット、辞書に使える。
リストの使用例

>>> a_list =list(range(10))
>>> a_list
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a_list = [x**2 for x in a_list]  --List comprehension
>>> a_list
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

If を使い、要素のFilteringをしてから処理することもできる。下はリスト中、偶数だけを処理して新しいリストを作成した例。 

>>> a_list = list(range(10))
>>> a_list = [x**2 for x in a_list if (x%2 ==0)]
>>> a_list
[0, 4, 16, 36, 64]

Python Dictionary の キーと値をスワップして新しい辞書を作る。

>>> week_dict={'Mon':'月','Tue':'火','Wed':'水','Thu':'木','Fri':'金','Sat':'土','Sun':'日'}
>>> youbi_dict={value:key for key,value in week_dict.items()}
>>> youbi_dict
{'木': 'Thu', '土': 'Sat', '月': 'Mon', '火': 'Tue', '水': 'Wed', '日': 'Sun', '金': 'Fri'}
>>> week_dict
{'Mon': '月', 'Fri': '金', 'Tue': '火', 'Sat': '土', 'Sun': '日', 'Wed': '水', 'Thu': '木'}
>>> week_dict['Fri']
'金'
>>> youbi_dict['日']
'Sun'

辞書は順番はキープしないのだ。

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年でもとが取れる計算になる。

困ったときはログファイル

Cubieboard2 (Arm7 Cortex Dual core 1GHz, 1GByte Ram, 4GByte Flash, OS=armhf debian 7) という、約60ドルで中国から購入したデベロッパーボードを使って運営しているホームサーバーの管理にISPConfig3という管理ソフトを導入して使用している。 Mailサーバー、Webサーバー、DNSそしてnginxプロキシなどをWEBブラウザから一括管理できるので重宝している。
このツール、HowtoForgeというサイトでサポートされていて、”Perfect Server” というシリーズで多様な組み合わせのサーバー設定のチュートリアルが掲載されている。 たとえばこの記事はOSはDebian,サーバープロキシにnginx, mailにはDoveCot、DNSにはBindを使ったサーバー構築の手順が述べられており、実は自分のサーバーはこれを参考にして立ち上げた。(DNSとNGINX、PHP、MySQLの部分はともかく、メールサーバーとメールフィルターの設定は自分ひとりの能力では手も足も出なかった。きちんと設定できたのは上の記事のおかげである)
 最近バージョンのアップデートをしようと思い立ち、コントロールパネルに指示されているiSPsonfig-update.shというコマンドを実行してみた。  アップデート自体はまったく問題なく行えたのだが、 コントロールパネルにログインしようとしてみたところいつもログイン画面が出るはずのurlが空っぽのページになっている。 
他のサービス(メール、Webサイト、DNS、SSHなど)は普通に動いているので、IPSConfigのダッシュボードへのログインが表示できないという限定された不具合だ。 幸いなことにISPConfigのUpdateツールがまず実行するのは旧バージョンのバックアップなので最悪の場合はリストアを行えばよいが、ページのヘッダー情報を見てみると、エラー番号が500、Internal Server Errorとなっているので、これはPHPの実行時、ページレンダリングの途中でおかしくなっている、とあたりをつけた。 NginxのErrorLogを眺めてみると大当たり、Fatal Errorが記録されていた。

11:54:25 [error] 3452#0: *528 FastCGI sent in stderr: "PHP message: PHP Warning:  require_once(/usr/local/ispconfig/interface/lib/config.inc.php): failed to open stream: Permission denied in /usr/local/ispconfig/interface/web/index.php on line 31
PHP message: PHP Fatal error:  require_once(): Failed opening required '../lib/config.inc.php' (include_path='.:/usr/share/php:/usr/share/pear') in /usr/local/ispconfig/interface/web/index.php on line 31" while reading response header from upstream,云々

上のエラーメッセージはindex.phpの31行目config.inc.phpを読み込もうとしたところ、拒否されました。と言っている。 ../libr/config.inc.phpのアクセスレベルがきつすぎるようだ、。
そこでこのファイルを調べてみるとOwner,GroupともISPCONFIGとなっているのは良いとして、Ownerのみに読み書き権限があたえられており、Groupレベルで読み書き禁止となっている。  それではと、Groupレベルでの読み出しも許可に書き換えてみたところ、あっさりと復活した。

#  chmod g+r config.inc.php

これが普通とは思わない。何らかの理由でサーバーのワーカープロセスとファイルのオーナー情報が背反しているためにファイルアクセスできなくなっていると考える。 少し思い当たることがあって、同じサーバー内部でModxを使ったサイトを運営しているのだが、アップデートするたびにSetupフォルダーをマニュアルで削除しなくてはならない、という作業が発生している。 Setupフォルダーの削除はインストール画面でチェックをいれてやれば自動的に行ってくれるはずなのだが、このサーバーではそれができてない。

というわけで、本日わかったこと。
1. Linuxのアクセスレベル管理がいまいち理解できてないなあ。
2. Linux 不具合解析はまずError Logを読む事。