• redmineの wikiマクロで graphviz その4

    その3」を書いたのが3年以上前なのか。
    redmineのwikiにgraphvizを使った画像を埋め込めるようにするマクロ。
    https://github.com/tckz/redmine-wiki_graphviz_plugin

    graphviz_meマクロは、このマクロが埋め込まれているwikiページ全体をdotとみなして画像描画する。
    wiki編集中のプレビューの際に、wikiマクロに渡ってくるモデル(WIkiContent)が保存済のもののため、今現在編集している内容で描画できていなかった。(一旦保存する必要があった)
    よくよく考えてみれば、wikiマクロが呼び出されたときのselfがviewを指しているのでリクエストのパラメータも取得できるのだった。
    マクロの挙動がformの構造に依存するのはイヤだと思いつつも、保存しないでプレビューできたほうがマシか。

    編集中テキストのプレビューの場合は画像をdataスキームでimg@srcに直接入れちゃうことにした。

    <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUg・・・TkSuQmCC">
    古いブラウザだと表示できないけど。
    画像部分の通信サイズが大きくなるけどレスポンス一回で画像もHTMLも返せると、取得した編集中テキストをまるごと受け取って画像を返すactionを新設しなくていい。


    環境:
    CentOS 6.2 x64
    ruby-1.8.7-p352
    mysql-server-5.1.61
    graphviz-2.26.0
    redmine-1.3.0
     

  • redmine 1.3.0にしたら wiki絡みの展開順が変わってた

    自作のwikiマクロの引数で、wikiリンクと同じ記法でリポジトリ上のリソースを指定させている。
    {{macro(source:path/to/file)}}
    
    redmine 1.3.0からwikiリンクとマクロの展開順が変わり、先にwikiリンクが処理されるようになったみたい。
    冒頭のマクロ引数に対してHTMLリンクに展開済の文字列(HTML)が渡ってくるようになった。

      Redmine::WikiFormatting::Macros.register do
        desc '略'
        macro :some_macro do |wiki_content_obj, args|
        end
    end
    1.2.xの場合、args[0]に「source:path/to/file」
    1.3.0の場合、args[0]に「<a href="https://passing.breeze.cc/mt/projects/sample/repository/entry/path/to/file" class="source">source:path/to/file</a>」
    という文字列が渡ってくる。

    「!」をつけると展開抑止になるので当面これで回避。
    {{macro(!source:path/to/file)}}
    

    あるいは引数の受け取り方を変えて
    {{macro(param=source:path/to/file)}}
    
    とすればHTMLリンクに展開されず引数を受け取れる。


  • jenkinsの DRY pluginで CPD

    jenkinsを使って継続的インテグレーションを行なっている。
    数年前はCruiseControl .NETを使っていたのだけど、hudsonを試したときユーザフレンドリーさに打たれて乗り換えた)

    以前からmakeなどで1手順ビルドできる仕組みを作ることにはこだわりがあった。
    たけど、単にビルドの1手順化だけでなく、
    •  複数の環境でビルドしたものを統合(CIサーバに集約)
    •  リポジトリのコミットとビルドを結びつけ(さらにITSのチケットに結びつく)
    •  複数の環境で自動テスト実行、その結果とビルドの結びつけ
    •  ビルドのログやテストのログなど記録をとる(確認したいときにすぐ辿れる)
    継続的インテグレーション入門 開発プロセスを自動化する47の作法
    ということを手間なく繰り返し可能とする仕組みには大きな意味があると思う。

    SCM、自動テスト、ITSそれぞれ単独でも役立つけど、
    ビルドとこれらを結びつけられるCIの存在は大きい。


    で、そのビルドと結びついた記録を取りたいものの1つがコードメトリクス。
    気にしている指標はいくつかあるけど、コードクローンについて。

    コードクローンの検出にCPD(PMD)を使っている。
    CPDのレポートxmlをjenkinsのDRY Pluginに食わせるだけ。ビルドごとの静的解析の結果をとりまとめてくれるプラグインでトレンドを見ることができる。
    正直に言えばjenkinsのビュー内でコードクローン部分そのものを見るのはあまり意味が無いというかかえって見づらいと思っている。eclipseにPMDプラグインをインストールしてクローン部分にアクセスする方が便利。
    あくまでjenkins上では時系列(ビルド)でコードクローンの増減を概観したい。


    ここの環境ではjenkinsのmasterをlinux上で動かしている。
    CPDの実行はWindowsスレーブ上で行なっている。
    入力はSJIS(MS932)でエンコードされたjavaソース。
    jenkinsのslave配下でjavaモジュールのビルドをantで行う。同様にantでCPDのレポートを作成している。

    PMDのlib下jarをCLASSPATHに指定してantタスクを定義
        <path id="cp.cpd">
            <fileset dir="${pmd.lib}">
                <include name="*.jar"/>
            </fileset>
        </path>
    
        <taskdef name="cpd" classpathref="cp.cpd" classname="net.sourceforge.pmd.cpd.CPDTask" />

    cpdタスクを実行
        
    <cpd encoding="Windows-31J" minimumTokenCount="100" format="xml" language="java" outputFile="${reports.cpd}/cpd.xml"> <fileset dir="${src.dir}"> <include name="**/*.java"/> </fileset> </cpd>

    で、後はjenkinsのワークスペースに出力されたxmlのpathをDry Pluginの入力に設定するだけ。


    当初、cpdタスクの入力エンコーディングを"MS932"にしていた。出力XMLのxml宣言にあるencodingも"MS932"になるのだけどこのままDry Pluginに読み込ませようとするとエラーになってしまう。
    Dry Pluginのソースをgithubからcloneして、自動テストの入力xmlのencodingをMS932に書き換えて実行したらスタックトレースに
    「Invalid encoding name "MS932".」と出ていた。
    org.apache.xerces.*が使われるから?


    環境:

    Windows 7 x64
     JDK6 u26 x86
     ant-1.8.2
    CentOS 5.6 x64
     JDK u26 x64
     ant-1.8.1

  • MT5に移行した

    「GAEに移行した」で書いたようにここのサイトは、手元のサーバ上においてMTで編集/生成した静的HTMLを、GAEのアプリケーションにリソースとして組み込みServletで返しているだけなので、MT4でもMT5でも関係ないといえばない。

    MT4のときはSQLiteを使っていたので、MySQLに移行せざるを得なかった。
    • [MT4]システムメニューからバックアップ
    • [MT4]MySQLにMT用のDBとユーザを作成
    • [MT4]mt-config.cgiを書き換えてMySQLを参照する設定に。
    • [MT4]この状態でmt.cgiにアクセスすると新規セットアップになるので、適当に。
    • [MT4]システムメニューからバックアップを復元
    • [MT5]MT5のファイルをおいてアップグレード→再構築
    てな感じで移行自体はできたんだけど、よく見るとカテゴリのリンクがまったく張られていない。
    なんでかと思ったら全ての記事からカテゴリの情報が消えてた!!

    ちまちまちまちま全記事にカテゴリを設定しなおすはめに。
    記事の一括編集でカテゴリ設定できることに途中まで気がつかず無駄にしんどかった。あーぁ。

    結果的に過去のエントリを見返すことになったのだけど、今も使ってるアプリ/OSSが結構古いバージョンのときから使ってたので驚いた。

    環境:
     CentOS 5.5 x86
      MovableType 5.04


  • Arduinoと ATtiny2313で SPI

    気がついたら前回工作してから半年もたってた。
    SN3E0090.jpg

    ArduinoからATtinyに指示を送ってモーターの制御をする、てなことをやるつもり。で、まずはSPIで指示を送り、これに従って何かする、ことをやってみたい。

     ※以下の内容は単にやってみたことの記録です。すべて無保証で、障害・損害・不利益・不都合に対し、筆者は一切の責任を負いません。

    SPI自体についてはこのへんを参照。
    なんでSPIを選んだかというと、
    I2Cよりも、仕組みが単純、転送速度も速くできるみたいだから。

    • Arduinoをマスター、AVR ATtiny2313Vをスレーブとする。
    • ATtiny2313にはSSがないみたいなので、PB4をLOWにしたらスレーブ選択、という体(てい)で。
    • マスターから送ったデータ8ビットを、スレーブ側でLED点灯で表現(面倒だったのでLEDは4つ。下位4ビットだけ・・・)&前回データを反転したものをマスターに返すことで、通信がうまくいったことを確認する。Arduino側はスレーブから受け取ったデータをSerialに書きだす。
    ATtiny2313は、外部クリスタル8Mhzを使用かつCKDIV8を無効にしているので、システムクロックは8Mhz。
    電源はUSBからArduinoに給電。ATtinyはArduinoから出ている5Vを使う。
    spi_test.PNG


    マスター:
    最近公開されたarduino 0022ではSPIが標準ライブラリになっているので、マスター側はこれを利用した。

    #include <SPI.h>
    #include <util/delay.h>

    void setup()
    {
    Serial.begin(9600);

    SPI.begin();
    SPI.setBitOrder(MSBFIRST);
    SPI.setClockDivider(SPI_CLOCK_DIV8);
    SPI.setDataMode(SPI_MODE0);

    pinMode(2, OUTPUT);
    digitalWrite(2, HIGH);

    uint8_t d = 0;
    for (;;)
    {
    digitalWrite(2, LOW);
    uint8_t a = SPI.transfer(d);
    digitalWrite(2, HIGH);

    Serial.print(d, HEX);
    Serial.write(", ");
    Serial.println(a, HEX);
    d++;
    _delay_ms(300);
    }
    }


    void loop()
    {
    }


    スレーブ:

    試しながら学ぶAVR入門―マイコンの基礎と電子工作とWindowsアプリケーションの作り方 (SkiLL up mycomputerシリーズ)
    スレーブ側は、ATtinyのデータシートに、アセンブリ言語で書かれた実装例があるので、ニーモニックの説明を見つつC言語に書き下してみた。
    ニーモニックについてはデータシートに説明がある。

    外部割り込みがどういう挙動か知りたかったこともあり、SS相当のPB4で割り込みがかかるようにした。
    PB4がLOWになったら受信開始。8ビット受信する。受信にあたりマスターへの送信データは、前回受け取ったデータをビット反転したものとした。特に意味はない。
    受け取った8ビットのうち下位4ビットのON/OFFをPB0~PB3につないだLEDに反映する。


    #include <avr/interrupt.h>
    #include <avr/io.h>
    #include <util/delay.h>


    #define USCK PB7
    #define MOSI PB5
    #define MISO PB6


    volatile uint8_t triggered = 0;

    ISR(PCINT_vect)
    {
    if (!bit_is_set(PINB, 4))
    {
    triggered = 1;
    }
    }

    uint8_t spi_slave_receive(uint8_t send)
    {
    USIDR = send;
    USISR = (1<<USIOIF);
    while (!(USISR & (1<<USIOIF)));
    uint8_t receive = USIDR;

    return receive;
    }

    void spi_slave_init()
    {
    USICR = (1<<USIWM0)|(1<<USICS1);

    // MISO(PB6)は出力に
    DDRB |= _BV(MISO);
    // MOSI(PB5)/USCKは入力に
    DDRB &= ~(_BV(MOSI) | _BV(USCK));

    // MOSI(PB5)/USCK(PB7)プルアップ
    PORTB |= (_BV(MOSI) | _BV(USCK));
    }

    int main(void)
    {
    spi_slave_init();

    // LED(PB0..PB3)は出力に
    DDRB |= _BV(PB0) | _BV(PB1) | _BV(PB2) | _BV(PB3);

    // LEDを消灯
    PORTB &= ~(_BV(PB0) | _BV(PB1) | _BV(PB2) | _BV(PB3));

    // PB4プルアップ
    PORTB |= _BV(PB4);

    // PB4の変化割込み
    GIMSK |= _BV(PCIE);
    PCMSK |= _BV(PB4);

    sei();

    uint8_t d = 0x00;
    for (;;)
    {
    while (!triggered)
    {
    }

    // PB4がLOWになった

    // clear
    triggered = 0;


    // 1バイト受信+送信
    d = spi_slave_receive(~d);


    // display bits as LED
    for (int i = 0, check = 1; i < 4; i++, check*=2)
    {
    if (d & check)
    {
    PORTB |= check;
    }
    else
    {
    PORTB &= ~(check);
    }
    }
    }
    }


    おわり:
    ようやくマイコン間で8ビット転送できるようになった。
    普段やってることは、重層な抽象化レイヤの上に成り立っているので、8ビットどころかネットワークを超えて簡単に送り放題だし、RPCでもなんでもいくらでもやりようがある。たまにこうやってプリミティブなところから積み上げるのもいい訓練になるなと思った。

    環境:
     Windows 7 x64 Ultimate
      arduino 0022
      AVR Studio 4.18 + SP3
      WinAVR 20100110
    Arduino Duemilanove
    AVR ATtiny 2313V