大学のLANにログインするスクリプト

毎回パスワードを打つのは面倒なので。
普通にPOSTしてるだけです。

Pythonistaってアプリ使えばiPhoneでも動く。
パソコンなら適当にスクリプト書いてcron回せばいいんじゃない。

ID、パスワード、認証ページのURLは変えてください。

# coding: utf-8

from urlparse import urljoin
import requests


ROOT_URL = 'http://1.1.1.1:10080'
LOGIN = '/cgi-bin/adeflogin.cgi'
LOGOUT = '/cgi-bin/adeflogout.cgi'

# edit me
PAYLOAD = {
    'name': 'your_id',
    'pass': 'your_password',
}


def logout():
    return requests.post(urljoin(ROOT_URL, LOGOUT))
    

def login():
    return requests.post(urljoin(ROOT_URL, LOGIN), data=PAYLOAD)


if __name__ == '__main__':
    login()

日常がヘンになる瞬間

バイト中。23:55、閉店まであと5分、突然電子音が鳴る。うわマジかよ、注文が入った。やれやれと思いながら店を出たのが0:03。
いつものルートで配達に向かうと公園の前の道の角に人が立ってる。長髪の男の人。特に気にも留めない。
0:16、配達を終える。
帰り道、往路と同じ公園の角を通るルート。

ん、公園の前の角に人が立ってる。あれ、行きも人が立ってたよな。
暗い住宅街の街灯の真下に立ってるから目立つ。
ゆっくりと丁字路に近づく。

……………ん??長髪の男だ。あれ??同じ人だよな。行きに通ってから20分近く経ってるぞ、えぇ……ずっと同じ場所に立ってんのかコイツ………。
背中ぐらいまでボサーっとのびた髪、50代くらいか。Gパンに黒っぽいTシャツ。

店に帰るためには丁字路を右折してこのオッさんの目の前を通らなくてはいけない。何か嫌だなあ。
スピードを上げて一気に通り過ぎたいところだけど一時停止して安全確認。右見て左見てもう一回右を見て発進………!その瞬間オッさんが凄い勢いでコッチを向いて両手をバッって挙げた。んで首だけを凄えスピードでバッバッって左右に振ってんの。
それみた瞬間もう汗がブワーーーーーッッッって吹き出して、でもなんか時間はスローに感じて、しばらくそのままオッさんの方見ながらバイク乗ってた。


マジの話。

応用情報技術者試験合格しました

受かってた。

試験対策

午前

午前は毎年過去問から半分近く出題されるので、スマホで過去問道場を解きまくって足りないところを参考書で補う感じで試験前には安定して8割近く取れるようになります。
いきなり参考書から勉強を始めると挫折します。はじめは流し読み程度でいいです。
参考書はこれが持ち運びやすくて最低限必要な情報が纏められてるのでおすすめ。

【改訂版】 要点早わかり 応用情報技術者 ポケット攻略本 (情報処理技術者試験)

【改訂版】 要点早わかり 応用情報技術者 ポケット攻略本 (情報処理技術者試験)

マークシート式の試験が久し振りすぎて後半全部マークずれてたので見直しした方がいいです。

午後

午後は問1必答+10問から4問選択という形式なのでとりあえず過去問で選択問題を一通り解いてみて自分が解く問題を5〜6問に絞り込むと良いです。私は「アルゴリズム」「ネットワーク」「組み込み」と3問解いた所で「システムアーキテクチャ」が想像以上に難しかったので急遽「システム監査」に切り替え。
毎年「国語の問題」と言われてるシステム監査(問11)ですが、今回は異様に難しかったです。
アルゴリズム、ネットワークは得意な方なら安定して得点できると思います。
組み込みが恐らく一番簡単だったのではないでしょうか。問題を見て簡単なら組み込みを選択できるように準備をしておいて損はないでしょう。

感想とか

試験会場の近くにコンビニが無いことがあるのでお昼ご飯を持っていきましょう。
応用情報技術者試験、思ったより勉強になったなという感じです。何かこうふわっとしてた知識がちょっと補強されたような気がします。
応用情報に合格すると2年間は上位試験の午前Iが免除になるらしいので次はネットワークスペシャリストでも受けるかな〜

EKワゴンのステアリングを交換する

モモステを入手したので交換してみることにしました。EKワゴンには贅沢すぎるけど気にしない。
余談ですが「ハンドル」は和製英語で正しくは「ステアリング」と言うらしいです。

必要なもの

EK用のボスはこれ

【CMR】 ステアリングボス 817

【CMR】 ステアリングボス 817

バッテリーを外す

エアバッグの誤作動を防ぐためにバッテリーの端子を外して20分くらい放置します。エアバッグ誤爆すると余裕で骨折するくらいの威力があるらしいので慎重にいきましょう。
あ、バッテリーを外すときはマイナス端子が先ですよ。

ノーマルのステアリングを外す

放電が終わったら左右2つあるトルクスネジを外します。完全には外れないようになってるのである程度緩めるだけでOKです。

エアバッグとホーンのカプラを千切らないように外してからエアバッグユニットを外します。
二つあるカプラのうち黄色がエアバッグ、もう一つがホーン用。


次は真ん中についてるナットを17mmのレンチで緩めます。
完全に外しちゃうとギッチリ嵌ってるハンドルを力一杯引っこ抜いたときに顔面を直撃します。ステアリングを引っこ抜く時のコツは上下左右にグイグイ揺らすようにすると上手いこと抜けてくれます。

新しいステアリングを取り付ける

ボスと一緒にエアバッグ警告灯キャンセラー用の抵抗が入っているので黄色いカプラーに繋げます。繋げる場所は4箇所あるうちのマルをつけた2ヶ所。

ボスのナットを締めます。締め付けトルクは30N・m。馬鹿力で締めると簡単に割れるそうなので注意。ナットを締めるときは鍵を抜いた状態で左(or右)にいっぱいに切ってハンドルロックをかけてからやると一人でもやり易いですね。

ボスの穴からホーン用のカプラを通してステアリングをつける。

ホーンスイッチに端子を繋げて、

できた〜

カッコいい……けど思ったよりハンドル回すのが重くなった。

ちなみに保険でエアバッグ特約を付けてる場合は適用されなくなるのでご注意を。

Pythonを使ってWiiリモコンから音を出す

果たして自分以外にこんなことやりたい人がいるのか分からないですけど他にあまりにも情報が少ないので一応残しておきます。 基本的にはhttp://wiibrew.org/wiki/Wiimoteの通りです。

必要なもの

フォーマットについて

Wiiリモコンのスピーカーで使える音声ファイルのフォーマットには8bit符号付きPCMか4bitADPCMのどちらかを選べるようです。

ただADPCMの方はヤマハのチップにしか使われてないフォーマットらしく変換できなかったのでPCMを選択しました。(ffmpegがサポートしてるらしいけど詳しくは知らない)

ファイルを変換するにはsoxを使って

sox --norm input.mp3 -b 8 out.raw channels 1 rate 2000  # 8bit, 2khz, mono

でできます。

Bluetoothソケット

PyBluezでどうやってWiiリモコンと通信したのか一応補足。

import bluetooth

ADDR = '00:19:1D:30:D2:2C'  # wiiリモコンのMACアドレス
socket = bluetooth.BluetoothSocket(bluetooth.L2CAP)
socket.connect((ADDR, 0x13))  # ここでWiiリモコンの①と②を同時押し

def write(value):
    socket.send(('a2' + value).decode('hex'))


def read(bytes):
    return socket.recv(bytes).encode('hex')

wiiリモコンMACアドレスhcitool scanとするかbluetooth.discover_devices(lookup_names=True)で調べられます。 write()、read()でWiiリモコンにデータ送ったり受け取ったりできます。

頭の0xa2はこちらから送信するときは必ず付けなくてはいけないようです。 また、Wiiリモコンから送られてくるデータの1バイト目は必ずa1になってます。

コレだけでとりあえず必要なものは揃いましたね。

スピーカー初期化

Wikiによると

  1. スピーカーの有効化(0x14へ0x04を送信)
  2. スピーカーのミュート(0x19へ0x04を送信)
  3. レジスタ0xa20009へ0x01を書き込み
  4. レジスタ0xa20001へ0x08を書き込み
  5. レジスタ0xa20001へ7-byte configurationを書き込む
  6. レジスタ0xa20008へ0x01を書き込み
  7. ミュート解除(0x19へ0x00を送信)

とあります。順番に行きましょう。

スピーカー有効化

write('1404')

スピーカーのミュート、ミュート解除

2. スピーカーのミュート(0x19へ0x04を送信)

write('1904')

7. ミュート解除(0x19へ0x00を送信)

write('1900')

7-byte configuration

スピーカーを鳴らすための設定は以下のような7バイトのデータになってます。 00 FF RR RR VV 00 00

FF: フォーマット。0x40なら8bitPCM、0x00ならADPCM

RR RR: サンプリングレート。 PCMの場合 12000000/RATEの値を16進数にしたものがRR RRになります。但しリトルエンディアンなので注意。

どうもBluetoothドライバ他との兼ね合いで2kHzより上はうまく音が出ないみたいです。

2kHzなら 12000000/2000 = 6000 = 0x1770 となるのでRR RRは 70 17となります。

VV: ボリューム 0x00から0xffの範囲

ボリュームを0x40とすると今回必要な7-byte configurationは 00 40 70 17 40 00 00 のようになります。

レジスタへの書き込み

レジスタに書き込みをするには以下のような23バイトのデータを送ります。 (a2) 16 MM FF FF FF SS DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD

MM: 書き込むレジスタの種類。今回は0x04

FF FF FF : アドレス

SS: サイズ(bytes)

DD: データ。20バイトに満たない場合はデータを左詰め?で0で埋めます。

以上を踏まえて

3. レジスタ0xa20009へ0x01を書き込み 4. レジスタ0xa20001へ0x08を書き込み 5. レジスタ0xa20001へ7-byte configurationを書き込む 6. レジスタ0xa20008へ0x01を書き込み は、

write('1604a200090101000000000000000000000000000000')
write('1604a200010108000000000000000000000000000000')
write('1604a200010700407017400000000000000000000000')
write('1604a200080101000000000000000000000000000000')

音声データ送信

スピーカーの初期化が終わったら実際にデータを送信します。

音声データをWiiリモコン送信するときのフォーマットは

(a2) 18 LL DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD

DDはデータ。LLはバイト長…と思いきやビット長らしいです、ここで数時間詰まりました(よく見たらWikiにもちゃんと書いてある)

あとは実際にガンガン送信するだけなんですけどもう一つ重要な事があって、それは「設定したサンプルレートに合わせた間隔でデータを送る」ということです。つまり8bit、サンプルレートが2kHzなら2kB/s、Wiiリモコン送れる音声データは一度に20バイト。

ということは結局10ミリ秒間隔で送信すれば良いことになります。 この間隔がちょっとでも違うと全く音が出ません。ここでも数時間取られましたよ…。

まとめると

こうなります。書き殴りの汚いコードなのは許してね。

import time

import bluetooth


def write(value):
  s.send(('a2' + value).decode('hex'))


def recv():
  return r.recv(25).encode('hex')


def init_speaker():
  write('1404')
  write('1904')

  write('1604a200090101000000000000000000000000000000')
  write('1604a200010108000000000000000000000000000000')
  write('1604a200010700407017400000000000000000000000')
  write('1604a200080101000000000000000000000000000000')

  write('1900')


def send_song(songname, dur=0.01):
  f = open(songname).read().encode('hex')
  for i in range(len(f)/20):
    write('18a0' + f[i*40:(i+1)*40])
    time.sleep(dur)

ADDR = '00:19:1D:30:D2:2C'

r = bluetooth.BluetoothSocket(bluetooth.L2CAP)

r.connect((ADDR, 0x13))


write('11f0')  # LEDの点滅を止める

init_speaker()
send_song('out.raw')

実際に動いてるとこ

うーん……楽しい!!!!!!!!!!!!!

たまに何故か音が出ない時があって、どうもスピーカーの初期化に失敗してるみたいです。そういうときはinit_speaker()を何回か繰り返すと音が出るようになります。

ちなみにPythonWiiリモコン使いたいだけならcwiidってライブラリがあるのでそっち使ったほうがいいです。ただ自分でWiiリモコンぽちぽち押しながらWikiとにらめっこしてコード書くのも楽しいですね。

Skype4Pyで作ったBotが反応しなくなった

前にSkype4Pyで特定のワードに反応して発言するBotを作ったのを思い出して久々に起動してみたら反応しなくなってた。

Skype4PyでBotを作る時はだいたい

import Skype4Py

skype = Skype4Py.Skype()


def hoge(msg, event):

  if event == Skype4Py.enums.cmsReceived: # "RECEIVED"

    pass# ほげほげ


skype.OnMessageStatus = hoge

みたいにするけど、最近のSkypeだと'RECEIVED'ってイベントが起こらない。どうもSkypeP2Pベースからクラウドベースに移行したのが原因らしい。

とはいえ今でもP2Pベースのチャットルームは作成できるのでそこにBotを参加させれば以前と同じように動作する。

どこでも良いので(グループでなくても可)チャットを開いて

/createmoderatedchat


と入力すると参加者が自分ひとりのグループが作成される。このグループは以前のようにP2Pベースなのであとは適当に参加者を追加して煮るなり焼くなり。ただこれもいつサポートが打ち切られるかわからないけど。