キーボード入力タイプのバーコードリーダ

工場向けの案件でキーボード入力タイプ(HID)のバーコードリーダを使用することがあります。

キーボードフックを使用してバーコード入力を取得するようにしていたのですが、取得したキーコードでは押されたキーが分かるだけなので、実際にはShiftキーやCtrlキーとのコンビネーションによって、キーコードから文字に変換する必要があります。
今までこの実装を適当に行っており、Shiftキーによる変換があまりできておらず、正しく読めない記号がありました。
今回、実装を見直しまして、ほぼ全てのパターンを網羅できたと思います。

以下がShiftキーを考慮した文字変換です。

return KeyCode switch {
    (int)Keys.Multiply => '*',
    (int)Keys.Separator => '|',
    (int)Keys.Add => '+',
    (int)Keys.Subtract => '-',
    (int)Keys.Decimal => '.',
    (int)Keys.Divide => '/',
    (int)Keys.Oemplus => shift ? '+' : ';',
    (int)Keys.Oemcomma => shift ? ' shift ? '=' : '-',
    (int)Keys.OemPeriod => shift ? '>' : '.',
    (int)Keys.Oem1 => shift ? '*' : ':',
    (int)Keys.Oem2 => shift ? '?' : '/',
    (int)Keys.Oem3 => shift ? '`' : '@',
    (int)Keys.Oem4 => shift ? '{' : '[',
    (int)Keys.Oem5 => shift ? '|' : '\\',
    (int)Keys.Oem6 => shift ? '}' : ']',
    (int)Keys.Oem7 => shift ? '~' : '^',
    (int)Keys.Oem102 => shift ? '_' : '\\',
    (int)Keys.NumPad0 => '0',
    (int)Keys.NumPad1 => '1',
    (int)Keys.NumPad2 => '2',
    (int)Keys.NumPad3 => '3',
    (int)Keys.NumPad4 => '4',
    (int)Keys.NumPad5 => '5',
    (int)Keys.NumPad6 => '6',
    (int)Keys.NumPad7 => '7',
    (int)Keys.NumPad8 => '8',
    (int)Keys.NumPad9 => '9',
    (int)Keys.D0 => '0',
    (int)Keys.D1 => shift ? '!' : '1',
    (int)Keys.D2 => shift ? '"' : '2',
    (int)Keys.D3 => shift ? '#' : '3',
    (int)Keys.D4 => shift ? '$' : '4',
    (int)Keys.D5 => shift ? '%' : '5',
    (int)Keys.D6 => shift ? '&' : '6',
    (int)Keys.D7 => shift ? '\'' : '7',
    (int)Keys.D8 => shift ? '(' : '8',
    (int)Keys.D9 => shift ? ')' : '9',
    >= (int)Keys.A and <= (int)Keys.Z => shift ? (char)KeyCode : (char)(KeyCode + 0x20),
    _ => char.ConvertFromUtf32(KeyCode)[0]
};

プログラムの違い

こんにちは mtj です。

プログラムと一概に言ってもそれを使用する場でかなりの意識の変化が必要になります。

  • 組み込み系
  • ネイティブのアプリ
  • WEBアプリ
  • サーバーサイドのプログラム

上記のそれぞれで考える事、注意する事がばらばらで同じ動作をさせようとしてもそれぞれで難易度が異なったりします。
また使用する言語、フレームワークの向き不向きもあるためかなり広い範囲での知識が必要になるように感じます

個別にどれをやっていたからどれが簡単等も少なく 基本はその分野について知っているかになると感じました
大まかなくくりの中にもどのネイティブ環境か フレームワークかCPUかだったり細かい違いがあるためさらに細かい分野知識も必要になりソフトが改めて奥が深いと感じます。

AI等も流行ってくるのでそれらも応用できるようになっていくのが時代の流れかもしれません。

C#13.0(.NET 9.0)のLockクラスとC#のlock構文について

C#のlockについて少し調べた際にたまたま知ったのですが、
C#13.0(.NET 9.0, 2024/11リリース)にてLockクラスが追加されたようです。
Lock クラス (System.Threading) | Microsoft Learn


// 上記記事からの引用となります
public sealed class ExampleDataStructure {
    private readonly Lock _lockObj = new();

    public void Modify() {
        lock (_lockObj) {
            // Critical section associated with _lockObj
        }

        using (_lockObj.EnterScope()) {
            // Critical section associated with _lockObj
        }

        _lockObj.Enter();
        try {
            // Critical section associated with _lockObj
        }
        finally { _lockObj.Exit(); }

        if (_lockObj.TryEnter()) {
            try {
                // Critical section associated with _lockObj
            }
            finally { _lockObj.Exit(); }
        }
    }
}

このLockクラスは従来のlock構文のロック対象objectのように宣言し、
従来のlock構文で使用できるほか、using構文でも使用でき、
またロック試行など細かな制御も可能なようです。

lock構文に対して、
不満(謎のobjectを用意する必要がある、構文が特殊、細かい制御が不可)があったので、
便利そうで良いなと思いました。

しかし、このLockクラスが追加されたのはどうも利便性向上のためではないらしく、
以下の2記事によるとパフォーマンス向上のためらしいです。
Lock クラス | ++C++; // 未確認飛行 C ブログ
【.NET 9.0】System.Threading.Lock のパフォーマンス #C# – Qiita

任意のオブジェクトに対してlockできるのはオーバーヘッドが大きい
とのことで、Qiitaの記事によると5%ほどパフォーマンス向上するとのことです。

そこで知ったのですが、そもそもC#には排他制御を司るMonitorクラスが存在し、
lock構文はMonitorクラスにより排他制御の糖衣構文のようです。
(以前からやろうと思えば細かい制御もできたんですね。。。)
マルチスレッド – C# によるプログラミング入門 | ++C++; // 未確認飛行 C

その糖衣構文がLockクラスの追加により、
ロック対象に今回のLockクラスのインスタンスに指定した場合に
Monitor使用のコードの代わりにLockによるコードへの置換に変更されるとのことです。

なので、C#13.0では基本的にはlock構文にLockクラスを併用するのが良いかと思われます。
以上、Lockクラスとlock構文についてでした。

※それともう一つ、数値型の単純な演算をアトミックに行えるInterlockedクラスの存在も
 上記のQiita記事内で初めて知りました。
 色々と便利なクラスがあったんですね。。。

I/Oユニット

先日の案件でSUS株式会社のI/OユニットSiOtを使用しました。

いつもはコンテックのI/Oユニットを使用していますが、今回は配線が楽なのと、メーカからスイッチBOXも購入出来るのでSiOtを使用してみました。
I/Oの配線はコネクタ式なので、購入したスイッチBOXを差し込むだけで配線完了です。

PCソフトからイーサネット通信で入力/出力が可能になっています。コマンドは簡単なのですぐに実装可能です。
通信時間が遅いので、同じ出力状態の場合は再送しないようになど細工は必要です。

コンテックと比較してメリットもデメリットもあるので、案件によって使い分けようと思います。
たぶん、PLCと接続する場合はコンテックが良く、ランプ・スイッチ・センサなどに直接接続する場合はSUSが良いと思われます。