Wirenboard 5の電子インクまたはGoでバーコードを描く

こんにちは、Habr! 開発プロセス中に、アプリケーションをテストするための自転車ツールを発明しなければならない場合があり、それらの一部は、たとえばホームオートメーションで役立つことがあります。 これは私の個人的な経験からのケースです。 モバイルデータ収集端末用のアプリケーションを開発する際、バーコードを紙に印刷せずにレーザースキャナーをテストする必要がありました。 残念ながら、これらのスキャナーは通常の画面から読み取ることができません。 彼らに紙を与えてください、しかし、彼らはまた、電子ペーパーがとても好きでした。



画像



Habr E-bookのディスプレイとしての記事を思い出しました。古い半死状態のSony PRS-505リーダーを棚から取り出して、自動化コントローラーの画面の役割で第二の人生を送ることにしました。 ただし、フラッシュメモリ経由で写真を送信することはお勧めできません。 電子書籍のRAMを直接操作する方法を学ぶ必要がありました。 これにより、表示速度と信頼性が向上します。 Goでの描画の経験をバーコードジェネレーターの例と共有し、Wirenboar 5コントローラーを介して電子書籍に表示させてください。



タスク



  1. 壊れることはありません。 新しい機能を追加するだけです。
  2. 電子ブックはポートをリッスンし、 1秒以内に画像を表示できる必要あります
  3. RAMのバッファのみを使用し、フラッシュメモリは使用しない
  4. great ddコマンドで出力をテストする
  5. Goで目的のサイズのバーコードを描画し、キャンバスの中央に配置します
  6. 画像を電子書籍のクリップボードに転送する
  7. 結果をお楽しみください


USB経由のRAMドライブ



Sony PRS-505にはwi-fiがなく、USBガジェットカーネルモジュールのg_file_storageのみがあるため、これが画像をすばやく転送する唯一の方法です。 幸いなことに、 PRSPlusのファームウェアは、電子書籍の電源を入れたときに任意のスクリプトを実行できます。 必要なのは、必要なファイルをディレクトリ/データベース/システム/ PRSPlusフォルダーに入れるだけで、prsp.shスクリプトがブート時に起動されます。



フラッシュメモリをバッファとして使用することはできません。そのため、USB経由でアクセスできるRAMに小さなtmpfsディスクが必要です。g_file_storageカーネルモジュールをアンロードし、USB経由で作成されたRAMディスクを公開するために必要なパラメーターをロードする必要があります。 次に、特定の領域の変更を追跡し、電子インクディスプレイに画像を表示する必要があります。



prsp.sh
#!/ bin / sh

echo $ '\ n ================ \ nSTART SCRYPT \ n' >> / dev / console



#TODO "代わりにカーネルイベントが必要です。そして、最下部にスリープします"

関数waitnewdata

{

echo $ '\ n ================= \ n新しいデータを待つ\ n' >> / dev / console



#画像ファイルの変更時間のみ表示

MODIFYTIMEOLD = `ls -l --full-time /tmp/raw.img | awk '{print $ 9}' '

MODIFYTIMENEW = $ MODIFYTIMEOLD



while ["$ MODIFYTIMEOLD" == "$ MODIFYTIMENEW"]

する

MODIFYTIMENEW = `ls -l --full-time /tmp/raw.img | awk '{print $ 9}' '



寝る0.2

やった



if ["$ MODIFYTIMEOLD"!= "$ MODIFYTIMENEW"]

それから

派手な

fi

}



関数showpic

{

echo $ '\ n ================ \ n新しいデータを受信\ n' >> / dev / console



#最適なクリアe-inkのためのバック画面の生成(オプション)

dd if = / dev / zero of = / tmp / img.raw bs = 1k count = 480

/ tmp / showpic /tmp/img.raw



dd if = / tmp / raw.img of = / tmp / img.raw bs = 1k count = 480

/ tmp / showpic /tmp/img.raw



waitnewdata

}



#ldconfig

PATH = "/ usr / local / bin:/ usr / bin:/ bin:/ usr / bin / X11:/ usr / games:/ usr / local / sony / bin:/ usr / sbin:/ sbin"

LD_LIBRARY_PATH = "/ Data / opt / sony / ebook / application:/ lib:/ usr / lib:/ usr / local / sony / lib:/ opt / sony / ebook / lib"

エクスポートパスLD_LIBRARY_PATH



#初期日付を設定

/ビン/日付0101000007



#カーネルモジュールのアンロード

rmmod g_file_storage



#生ファイル1Mbを作成

dd if = / dev / zero of = / tmp / raw.img bs = 1k count = 1k



grep Data / proc / mtd> / dev / null

[$? == 0]; それから



NUM = `grep Data / proc / mtd | awk -F: '{print $ 1}' | awk -Fd '{print $ 2}' '

insmod /lib/modules/2.4.17_n12/kernel/drivers/usb/g_file_storage.o file = / dev / mtdblock $ NUM、/ dev / sdmscard / r5c807b、/ dev / sdmscard / r5c807a、/ tmp / raw.img ProductID = $ MODEL VendorSpecific = $ VENDOR sn_select = 0 iSerialNumber = $ ID

他に

insmod /lib/modules/2.4.17_n12/kernel/drivers/usb/g_file_storage.o file = / dev / sdmscard / r5c807b、/ dev / sdmscard / r5c807a、/ tmp / raw.img ProductID = $ MODEL VendorSpecific = $ VENDOR sn_lect = 0 iSerialNumber = $ ID

fi



#kbookアプリケーションの起動

nohup / opt / sony / ebook / application / tinyhttp> / dev / null&



cp /データ/データベース/システム/ PRSPlus / showpic / tmp /



waitnewdata



psrp.shスクリプトのハイライト





これで、私たちの電子書籍は聞くことができ、同時に、以前と同じように本を読むことができます。 スクリプトを開始し、画像を転送するために留意する必要がある主なことは、USB e-bookがオンになっている場合、ケーブルを接続しないことです。 それ以外の場合、本はprsp.shスクリプトなしでロードされます。 つまり、最初に本の電源を入れ、シェルがロードされるのを待ってから、USBケーブルを接続します。 (この機能はデフォルトでPRSPlusファームウェアに登録されていますが、必要に応じて変更して独自のイメージを作成することもできます)



確認する



電子書籍で[リセット]をクリックし、ダウンロードが完了するのを待って、USBケーブルを接続します。 確認のために、テスト画像を送信できます。 たとえば、Ubuntuの場合、これは次のように実行できます。



リーダーが読み込まれたときにスクリプトが正常に起動した場合、USB経由で接続すると、サイズが1 MBのデバイスが表示されます。



 fdisk -l
      
      





次の行を見つけます。



 Disk /dev/sdx: 1 MB, 1048576 bytes
      
      





これで、電子書籍/dev/sdx



のRAMが/dev/sdx







jpegから変換するには、djpegが必要です。必要なパッケージをインストールします。



 apt-get install libjpeg-turbo-progs
      
      





次に、お気に入りのエディターでJPEGファイルを作成し、サイズを600x800にして、電子書籍に送信します。



 djpeg -pnm -grayscale test.jpg | dd bs=1 skip=15 | dd of=/dev/sdx bs=480k
      
      





このパイプラインでは、jpegをモノクロのpgmに変換し、ヘッダーをスキップして、単一ブロック内の480Kbを/ dev / sdxデバイスに転送します。 そして、結果が表示されます。



バーコードジェネレーターとデバイスへの送信



Golangでバーコードを描画するには、追加のライブラリが必要です。



 go get github.com/boombuler/barcode go get golang.org/x/image/bmp
      
      





main.go
 package main import ( "bytes" "fmt" "image" "log" "os" "image/color" "image/draw" "golang.org/x/image/bmp" "syscall" "github.com/boombuler/barcode" "github.com/boombuler/barcode/ean" "github.com/boombuler/barcode/qr" ) func main() { switch string(os.Args[2]) { case "qr": base64 := os.Args[3] log.Println("Original data:", base64) code1pixel, err := qr.Encode(base64, qr.L, qr.Unicode) if err != nil { log.Fatal(err) } log.Println("Encoded data: ", code1pixel.Content()) if base64 != code1pixel.Content() { log.Fatal("data differs") } log.Println("Encoded data: ", code1pixel.Content()) if base64 != code1pixel.Content() { log.Fatal("data differs") } codeScalled, err := barcode.Scale(code1pixel, 300, 200) if err != nil { log.Fatal(err) } drtest(codeScalled) case "ean": // code, err := ean.Encode("123456789012") code1pixel, err := ean.Encode(os.Args[3]) if err != nil { log.Fatal(err) } log.Println("Encoded data: ", code1pixel.Content()) codeScalled, err := barcode.Scale(code1pixel, 300, 300) if err != nil { log.Fatal(err) } drtest(codeScalled) } } func drtest(imgSrc image.Image) { // create a new Image with the same dimension of image newImg := image.NewGray(image.Rect(0, 0, 600, 800)) // we will use white background to replace background // you can change it to whichever color you want with // a new color.RGBA{} and use image.NewUniform(color.RGBA{<fill in color>}) function draw.Draw(newImg, newImg.Bounds(), &image.Uniform{color.White}, image.Point{}, draw.Src) // paste image OVER to newImage draw.Draw(newImg, newImg.Bounds().Add(image.Point{150, 300}), imgSrc, imgSrc.Bounds().Min, draw.Over) buf := new(bytes.Buffer) err := bmp.Encode(buf, newImg) if err != nil { fmt.Println(err) os.Exit(1) } send_s3 := buf.Bytes() fmt.Println("OK") if os.Args[1] != "false" { devout(send_s3[1078:]) } } func devout(buffer []byte) { // disk := "/dev/sde" disk := os.Args[1] var fd, numread int var err error fd, err = syscall.Open(disk, syscall.O_RDWR, 0777) if err != nil { fmt.Print(err.Error(), "\n") return } //WRITE numread, err = syscall.Write(fd, buffer) if err != nil { fmt.Print(err.Error(), "\n") } fmt.Printf("Numbytes write: %d\n", numread) // fmt.Printf("Buffer: %x\n", buffer[:1000]) err = syscall.Close(fd) if err != nil { fmt.Print(err.Error(), "\n") } }
      
      





コードのハイライト:



  1. EANの例を使用して、最初に1ピクセルの厚さのバーコードを描画します。



     code1pixel, err := ean.Encode(os.Args[3])
          
          





  2. 希望のサイズに伸ばします:



     codeScalled, err := barcode.Scale(code1pixel, 300, 300)
          
          





  3. 画面サイズに合わせて600x800のキャンバスを作成します。



     newImg := image.NewGray(image.Rect(0, 0, 600, 800))
          
          





  4. 目的の色で塗りつぶします。



     draw.Draw(newImg, newImg.Bounds(), &image.Uniform{color.White}, image.Point{}, draw.Src)
          
          





  5. キャンバスにバーコード画像を追加します。



     draw.Draw(newImg, newImg.Bounds().Add(image.Point{150, 300}), imgSrc, imgSrc.Bounds().Min, draw.Over)
          
          





  6. 次に、記録のためにデバイスを開き、BMPヘッダーを除くデータをそこに送信します。



     devout(send_s3[1078:])
          
          





Wirenboard 5でのクロスコンパイル



Wirenboard開発者は、Dockerコンテナに基づく非常に便利なクロスコンパイルツールを提供します。 しかし、この記事の枠組みでは、それを考慮しません。 ARMv5では、シンプルなアプリケーションを1つのチームで組み立てることができます。



 GOOS=linux GOARCH=arm GOARM=5 go build main.go
      
      





すべてをWirenboard 5に転送します。



 scp main root@192.168.xx:/tmp
      
      





Wirenboardに移動して、サイズが1 MBのデバイスの名前を見てください。この例では/ dev / sddです。



以下を開始します。



 /tmp/main /dev/sdd qr "Privet Habr"
      
      









結論



電子書籍を画面として使用するのは現実的です。 その可能性により、電子インク技術はインテリアデザインでの使用を促進します。 E-inkスクリーンは、特に明るい壁でよく見えます。 ホームコントローラーから有用な情報を表示できます。



ご清聴ありがとうございました!



PSソース、 こちらこちらをご覧ください。 電子書籍用ファームウェアPRSPlusはこちら



All Articles