200 lines
5.6 KiB
Ruby
200 lines
5.6 KiB
Ruby
# frozen_string_literal: true
|
||
|
||
module Libptouch
|
||
# 32 バイトのステータス応答を Hash に展開する(C の libptouch_status_fprint と同じ区分)。
|
||
module StatusHash
|
||
class << self
|
||
def decode(raw)
|
||
unless raw.bytesize == STATUS_LENGTH
|
||
raise ArgumentError,
|
||
"expected #{STATUS_LENGTH} bytes, got #{raw.bytesize}"
|
||
end
|
||
|
||
s = raw.bytes
|
||
|
||
{
|
||
header_ok: s[0] == 0x80 && s[1] == 0x20,
|
||
header: [s[0], s[1]],
|
||
brother_code: s[2],
|
||
brother_code_char: s[2] >= 32 && s[2] < 127 ? s[2].chr(Encoding::ASCII_8BIT) : nil,
|
||
model: model_entry(s[4]),
|
||
region_code: s[5],
|
||
region_char: s[5] >= 32 && s[5] < 127 ? s[5].chr(Encoding::ASCII_8BIT) : nil,
|
||
battery: labeled(BATTERY, s[6]),
|
||
extended_error: extended_error_entry(s[7]),
|
||
error_info1: error_info1(s[8]),
|
||
error_info2: error_info2(s[9]),
|
||
media_width: media_width_entry(s[10], s[17]),
|
||
tape_kind: labeled(MEDIA_KIND, s[11]),
|
||
color_count: s[12],
|
||
font_jp: s[13],
|
||
font: s[14],
|
||
mode: s[15],
|
||
density: s[16],
|
||
status_kind: labeled(STATUS_KIND, s[18]),
|
||
phase_type: s[19],
|
||
phase_number: [s[20], s[21]],
|
||
notification_number: s[22],
|
||
extended_section_bytes: s[23],
|
||
tape_color: labeled(TAPE_COLOR, s[24]),
|
||
text_color: s[25],
|
||
raw_hex: raw.unpack1("H*"),
|
||
raw_bytes: s.dup
|
||
}
|
||
end
|
||
|
||
private
|
||
|
||
def model_entry(code)
|
||
{
|
||
code: code,
|
||
name: MODEL_NAMES[code],
|
||
ascii_char: code >= 32 && code < 127 ? code.chr(Encoding::ASCII_8BIT) : nil
|
||
}
|
||
end
|
||
|
||
def labeled(table, byte)
|
||
{
|
||
code: byte,
|
||
label: table[byte]
|
||
}
|
||
end
|
||
|
||
def extended_error_entry(byte)
|
||
h = { code: byte, label: EXTENDED_ERROR[byte] }
|
||
h[:none] = true if byte.zero?
|
||
h
|
||
end
|
||
|
||
def media_width_entry(w, len_byte)
|
||
entry = labeled(MEDIA_WIDTH, w)
|
||
if w == 0x15 && len_byte != 0
|
||
entry[:media_length_code] = len_byte
|
||
entry[:media_length_note_mm] = len_byte
|
||
end
|
||
entry
|
||
end
|
||
|
||
def error_info1(b)
|
||
{
|
||
raw: b,
|
||
media_missing: !!(b & 0x01),
|
||
media_end: !!(b & 0x02),
|
||
cutter_jam: !!(b & 0x04),
|
||
battery_weak: !!(b & 0x08),
|
||
high_voltage_adapter: !!(b & 0x40)
|
||
}
|
||
end
|
||
|
||
def error_info2(b)
|
||
{
|
||
raw: b,
|
||
media_mismatch: !!(b & 0x01),
|
||
comm_error: !!(b & 0x04),
|
||
comm_buffer_full: !!(b & 0x08),
|
||
cover_open: !!(b & 0x10),
|
||
heat_error: !!(b & 0x20),
|
||
tip_detection_error: !!(b & 0x40),
|
||
system_error: !!(b & 0x80)
|
||
}
|
||
end
|
||
end
|
||
|
||
MODEL_NAMES = {
|
||
0x6F => "PT-P900W",
|
||
0x70 => "PT-P950NW",
|
||
0x71 => "PT-P900",
|
||
0x78 => "PT-P910BT",
|
||
0x68 => "PT-P750W",
|
||
0x76 => "PT-P710BT"
|
||
}.freeze
|
||
|
||
MEDIA_WIDTH = {
|
||
0x00 => "テープなし / 未装着",
|
||
0x04 => "3.5 mm",
|
||
0x06 => "6 mm",
|
||
0x09 => "9 mm",
|
||
0x0C => "12 mm",
|
||
0x12 => "18 mm",
|
||
0x18 => "24 mm",
|
||
0x24 => "36 mm",
|
||
0x15 => "FLe 21 mm 幅(長さはメディア長バイト参照)"
|
||
}.freeze
|
||
|
||
MEDIA_KIND = {
|
||
0x00 => "テープなし",
|
||
0x01 => "ラミネートテープ",
|
||
0x03 => "ノンラミネートテープ",
|
||
0x04 => "ファブリックテープ",
|
||
0x11 => "ヒートシュリンクチューブ (HS 2:1)",
|
||
0x13 => "FLe テープ",
|
||
0x14 => "フレキシブルIDテープ",
|
||
0x15 => "サテンテープ",
|
||
0x17 => "ヒートシュリンクチューブ (HS 3:1)",
|
||
0xFF => "非対応テープ"
|
||
}.freeze
|
||
|
||
BATTERY = {
|
||
0x00 => "フル",
|
||
0x01 => "ハーフ",
|
||
0x02 => "ロー",
|
||
0x03 => "要充電",
|
||
0x04 => "AC アダプター使用中",
|
||
0xFF => "不明"
|
||
}.freeze
|
||
|
||
TAPE_COLOR = {
|
||
0x01 => "白 (White)",
|
||
0x02 => "その他 (Other)",
|
||
0x03 => "透明 (Clear)",
|
||
0x04 => "赤 (Red)",
|
||
0x05 => "青 (Blue)",
|
||
0x06 => "黄 (Yellow)",
|
||
0x07 => "緑 (Green)",
|
||
0x08 => "黒 (Black)",
|
||
0x09 => "透明(文字白)",
|
||
0x20 => "白(マット) (Matte White)",
|
||
0x21 => "透明(マット) (Matte Clear)",
|
||
0x22 => "銀(マット) (Matte Silver)",
|
||
0x23 => "金(サテン) (Satin Gold)",
|
||
0x24 => "銀(サテン) (Satin Silver)",
|
||
0x30 => "青(D)",
|
||
0x31 => "赤(D)",
|
||
0x40 => "オレンジ(蛍光)",
|
||
0x41 => "黄(蛍光)",
|
||
0x50 => "ピンク(S)",
|
||
0x51 => "グレー(S)",
|
||
0x52 => "グリーン(S)",
|
||
0x60 => "イエロー(F)",
|
||
0x61 => "ピンク(F)",
|
||
0x62 => "ブルー(F)",
|
||
0x70 => "白(チューブ)",
|
||
0x90 => "白(フレキ)",
|
||
0x91 => "黄(フレキ)",
|
||
0xF0 => "クリーニング",
|
||
0xF1 => "ステンシル",
|
||
0xFF => "非対応"
|
||
}.freeze
|
||
|
||
STATUS_KIND = {
|
||
0x00 => "印刷終了",
|
||
0x01 => "エラー発生",
|
||
0x02 => "IF モード終了",
|
||
0x03 => "パワーオフ(未使用扱い)",
|
||
0x04 => "通知",
|
||
0x05 => "フェーズ変更"
|
||
}.freeze
|
||
|
||
EXTENDED_ERROR = {
|
||
0x10 => "FLE のテープエンド",
|
||
0x1D => "高解像度/ドラフト印刷エラー",
|
||
0x1E => "アダプター抜き挿しエラー",
|
||
0x21 => "非対応メディアエラー"
|
||
}.freeze
|
||
end
|
||
|
||
def self.parse_status(raw)
|
||
StatusHash.decode(raw)
|
||
end
|
||
end
|