- 投稿日:2020-07-29T20:38:40+09:00
C#によるPOS開発入門(的な) 記事一覧
POS for .NET関連は企業で扱うことが多いからか、インターネット上の情報がかなり少ないので個人開発が大変。
— おーとま (@automatic_csp) June 11, 2020
MSDNと機器メーカーのサンプルをいつも以上にじっくり読み込まないといけない。POS関連の記事って少なくないですか……?
個人的に触る人が少ないのか、POS関連の開発についてのブログ等の記事はネット上にほとんどありません。Googleで「OPOS」や「POS for .NET」、「POS 開発」などを検索しても、MSDN以外に引っ掛かるのは
- OPOSって知ってますか?
- POS開発に強い会社5選!
といったところ。いざ開発してみようとなると、まわりに知っている人がいない限り、説明書を熟読して必要なドライバーをインストールし、機器メーカーや Microsoft が出しているサンプルを何日もかけて読み込むしかないわけです。
このサンプルを読み込む時間がもったいない。私はものを買ってから思い通りに扱えるようになるまで3か月もかかりました。
ということで、機器の購入からC#で機器を動作させるまでの手順を解説していこうと思います。この記事が開発のハードルを下げることに繋がれば嬉しいです。記事一覧
以下よりどうぞ。
その1: 開発用にPOS機器を購入する時のポイント
安価で日本製の機器を購入する方法と、その際の注意点を説明しています。
おまけとして、私のうろ覚えな記憶を基に書いた日本の機器メーカー一覧もあります。その2: POS機器を制御する何通りかの方法
POS機器を制御する何通りかの方法を、機器の種類別に説明しています。
その3: EPSON製のPOS機器をセットアップする
どのメーカーでも、セットアップの方法(ドライバーのインストールや使用機器の登録など)はホームページを見れば大体書いてあります。
しかしその中でも、EPSON製の機器についてはカスタマイズ性の高さからセットアップの方法がそこそこ複雑だったので、EPSON製に限って解説しました。
その4: POS for .NETでPOS機器を動かす準備中POS for .NETを利用してPOS機器を動作させる方法を説明しています。
- 投稿日:2020-07-29T20:38:40+09:00
C#によるPOS・サーマルプリンター開発入門(的な) 記事一覧
POS for .NET関連は企業で扱うことが多いからか、インターネット上の情報がかなり少ないので個人開発が大変。
— おーとま (@automatic_csp) June 11, 2020
MSDNと機器メーカーのサンプルをいつも以上にじっくり読み込まないといけない。POS関連の記事って少なくないですか……?
個人的に触る人が少ないのか、POS関連の開発についてのブログ等の記事はネット上にほとんどありません。Googleで「OPOS」や「POS for .NET」、「POS 開発」などを検索しても、MSDN以外に引っ掛かるのは
- OPOSって知ってますか?
- POS開発に強い会社5選!
といったところ。いざ開発してみようとなると、まわりに知っている人がいない限り、説明書を熟読して必要なドライバーをインストールし、機器メーカーや Microsoft が出しているサンプルを何日もかけて読み込むしかないわけです。
このサンプルを読み込む時間がもったいない。私はものを買ってから思い通りに扱えるようになるまで3か月もかかりました。
ということで、機器の購入からC#で機器を動作させるまでの手順を解説していこうと思います。この記事が開発のハードルを下げることに繋がれば嬉しいです。記事一覧
以下よりどうぞ。
その1: 開発用にPOS機器を購入する時のポイント
安価で日本製の機器を購入する方法と、その際の注意点を説明しています。
おまけとして、私のうろ覚えな記憶を基に書いた日本の機器メーカー一覧もあります。その2: POS機器を制御する何通りかの方法
POS機器を制御する何通りかの方法を、機器の種類別に説明しています。
その3: EPSON製のPOS機器をセットアップする
どのメーカーでも、セットアップの方法(ドライバーのインストールや使用機器の登録など)はホームページを見れば大体書いてあります。
しかしその中でも、EPSON製の機器についてはカスタマイズ性の高さからセットアップの方法がそこそこ複雑だったので、EPSON製に限って解説しました。その4: POS for .NETでPOS機器を制御する
POS for .NETを利用してPOS機器を動作させる方法を説明しています。
- 投稿日:2020-07-29T20:37:52+09:00
サーマルプリンターなどのPOS機器を制御する何通りかの方法
これは「C#によるPOS開発入門(的な)」と称して連載している記事の1つです。他はこちら
1. はじめに
POSの機器を制御する方法は何通りかありますが、その方法について基礎的な情報がネット上に全くと言って良いほど無かったので、ここで説明しようと思います。実際のコーディングについては、こちらの記事でPOS for .NETで制御する方法について説明しているので、良ければ合わせて参考にして下さい。
POS開発について勉強し始めた当時、私に教えてくれるような人など周りにいなかったため、ここに書いてあるのはサンプルやマニュアルの見ながらの完全独学な知識です。「ここ良くないよー」という所があれば教えて下さると泣いて喜びます。
2. この記事の対象読者
- POS開発に興味があるが、やったことは無くやり方も知らない人
- 面白そうだったので感熱プリンターを買ってみたものの、動かし方が分からず途方に暮れている人
3. サーマルプリンター・カスタマーディスプレイの場合
制御する方法は大きく分けて4通りあります。
- 地道にコマンドを送信する方法
- WPS準拠ドライバーを使用する方法
- メーカー独自のDLLからドライバーを呼び出す方法
- 統一規格に準拠したドライバーを使用する方法
地道にコマンドを送信する方法
一番初めに提供された方法であり、かつ最も低水準な方法です。
シリアルポート・パラレルポートにコマンドを送信して、機器を直接制御します。C#の場合はSystem.IO.Ports.SerialPort
を利用します。各メーカーで独自のコマンドを制定していることが多いです(例……スター精密: スターグラフィックモード/スターラインモード等、EPSON: ESC/POS、SATO: SBPL)。コマンドは基本的にASCIIで表されます。
権利の関係でサンプルを掲載することが出来ません。メーカーのマニュアル等を参照して下さい。ESC/POSのリファレンスはこちらです。WPS準拠ドライバーを使用する方法
メーカーがWPS準拠のドライバーを提供している場合は、
System.Printing
からドライバーを制御することが出来ます。
が、こんな業務用のごついプリンターをSystem.Printing
で動かすのって、何かカッコ悪くありません……? そう思うのは私だけでしょうか。
この方法のサンプルはそこら中にあると思うので割愛します。メーカー独自のDLLからドライバーを呼び出す方法
WPS準拠のドライバーをメーカー独自のDLLから呼び出して制御する、という形態をとっているものもあります。
メーカーがSDKを提供している場合は、このパターンが一番多い印象です。統一規格に準拠したドライバーを使用する方法
コマンドを送信して機器を直接制御する場合、メーカーによってコマンド体系が違うため、POSアプリケーションを開発・販売するには制御処理を機器のメーカー別に何種類も準備する必要がありました。
そこで、制御コードの統一規格を設け、機器メーカーにその規格に準拠したドライバーを提供させることで、どのメーカーの機器も同一のコードで制御することを可能にしました。こういった規格の1つがOPOS(POS for .NET1)です。4. キャッシュドロアの場合
制御する方法は、ドロアの接続方式によって変わります。
モジュラーケーブル(ドロアキックケーブル・DKD)接続の場合
電話の接続にも使われる6ピンのケーブルでサーマルプリンターに接続し、サーマルプリンターから信号を送信することでキャッシュドロアを開けます。
- PCからコマンドを送信する方法
- サーマルプリンターでの印刷時にドロアを開くよう設定する方法
- WPS準拠ドライバーを使用する方法
- メーカー独自のDLLからドライバーを呼び出す方法
- 統一規格に準拠したドライバーを使用する方法
USB接続の場合
PCにUSBケーブルで直接接続するタイプも存在します。
- PCからコマンドを送信する方法
- WPS準拠ドライバーを使用する方法
- メーカー独自のDLLからドライバーを呼び出す方法
- 統一規格に準拠したドライバーを使用する方法
この他にLAN接続のタイプ等もありますが、あまり多くはありません。
各方式の詳細は「サーマルプリンター・カスタマーディスプレイの場合」の項を参照して下さい。
5. バーコードリーダーの場合
PCに読み取ったバーコードの情報を送信する方式で2種類に分けられます。
- シリアル通信としてやりとりする場合
- キーボードをエミュレートする場合
シリアル通信としてやりとりする場合
System.IO.Ports.SerialPort
で接続しDataReceived
イベントを待機することで、読み取ったバーコードの情報を取得します。キーボードをエミュレートする場合
読み取ったバーコードの情報がキーボード入力されます。
6. 終わりに
この記事以外にもPOS開発関連の記事を投稿しています。もし良ければこちらからどうぞ。
POS for .NETは、OPOSを.NETで実装したものです。 ↩
- 投稿日:2020-07-29T20:37:52+09:00
POS機器を制御する何通りかの方法
これは「C#によるPOS開発入門(的な)」と称して連載している記事の1つです。他はこちら
1. はじめに
POSの機器を制御する方法は何通りかありますが、その方法について基礎的な情報がネット上に全くと言って良いほど無かったので、ここで説明しようと思います。
POS開発について勉強し始めた当時、私に教えてくれるような人など周りにいなかったため、ここに書いてあるのはサンプルやマニュアルの見ながらの完全独学な知識です。「ここ良くないよー」という所があれば教えて下さると泣いて喜びます。
2. この記事の対象読者
- POS開発に興味があるが、やったことは無くやり方も知らない人
- 面白そうだったので感熱プリンターを買ってみたものの、動かし方が分からず途方に暮れている人
3. サーマルプリンター・カスタマーディスプレイの場合
制御する方法は大きく分けて4通りあります。
- 地道にコマンドを送信する方法
- WPS準拠ドライバーを使用する方法
- メーカー独自のDLLからドライバーを呼び出す方法
- 統一規格に準拠したドライバーを使用する方法
地道にコマンドを送信する方法
一番初めに提供された方法であり、かつ最も低水準な方法です。
シリアルポート・パラレルポートにコマンドを送信して、機器を直接制御します。C#の場合はSystem.IO.Ports.SerialPort
を利用します。各メーカーで独自のコマンドを制定していることが多いです(例……スター精密: スターグラフィックモード/スターラインモード等、EPSON: ESC/POS、SATO: SBPL)。コマンドは基本的にASCIIで表されます。
権利の関係でサンプルを掲載することが出来ません。メーカーのマニュアル等を参照して下さい。ESC/POSのリファレンスはこちらです。WPS準拠ドライバーを使用する方法
メーカーがWPS準拠のドライバーを提供している場合は、
System.Printing
からドライバーを制御することが出来ます。
が、こんな業務用のごついプリンターをSystem.Printing
で動かすのって、何かカッコ悪くありません……? そう思うのは私だけでしょうか。
この方法のサンプルはそこら中にあると思うので割愛します。メーカー独自のDLLからドライバーを呼び出す方法
WPS準拠のドライバーをメーカー独自のDLLから呼び出して制御する、という形態をとっているものもあります。
メーカーがSDKを提供している場合は、このパターンが一番多い印象です。統一規格に準拠したドライバーを使用する方法
コマンドを送信して機器を直接制御する場合、メーカーによってコマンド体系が違うため、POSアプリケーションを開発・販売するには制御処理を機器のメーカー別に何種類も準備する必要がありました。
そこで、制御コードの統一規格を設け、機器メーカーにその規格に準拠したドライバーを提供させることで、どのメーカーの機器も同一のコードで制御することを可能にしました。こういった規格の1つがOPOS(POS for .NET1)です。4. キャッシュドロアの場合
制御する方法は、ドロアの接続方式によって変わります。
モジュラーケーブル(ドロアキックケーブル・DKD)接続の場合
電話の接続にも使われる6ピンのケーブルでサーマルプリンターに接続し、サーマルプリンターから信号を送信することでキャッシュドロアを開けます。
- PCからコマンドを送信する方法
- サーマルプリンターでの印刷時にドロアを開くよう設定する方法
- WPS準拠ドライバーを使用する方法
- メーカー独自のDLLからドライバーを呼び出す方法
- 統一規格に準拠したドライバーを使用する方法
USB接続の場合
PCにUSBケーブルで直接接続するタイプも存在します。
- PCからコマンドを送信する方法
- WPS準拠ドライバーを使用する方法
- メーカー独自のDLLからドライバーを呼び出す方法
- 統一規格に準拠したドライバーを使用する方法
この他にLAN接続のタイプ等もありますが、あまり多くはありません。
各方式の詳細は「サーマルプリンター・カスタマーディスプレイの場合」の項を参照して下さい。
5. バーコードリーダーの場合
PCに読み取ったバーコードの情報を送信する方式で2種類に分けられます。
- シリアル通信としてやりとりする場合
- キーボードをエミュレートする場合
シリアル通信としてやりとりする場合
System.IO.Ports.SerialPort
で接続しDataReceived
イベントを待機することで、読み取ったバーコードの情報を取得します。キーボードをエミュレートする場合
読み取ったバーコードの情報がキーボード入力されます。
6. 終わりに
この記事以外にもPOS開発関連の記事を投稿しています。もし良ければこちらからどうぞ。
POS for .NETは、OPOSを.NETで実装したものです。 ↩
- 投稿日:2020-07-29T12:28:10+09:00
C#で最小全域木
最小全域木とは簡単に説明するとグラフのすべての頂点は最も少ないコストの辺で構成された木のことです。
使用しているアルゴリズムはクラスカル法です。
これも簡単に言うとグラフから最もコストの少ない辺をループができないように追加するという処理を繰り返してすべての頂点を選択したところで終了します。Union Find
クラスカル法を実装するにあたってどの頂点がどの木に所属しているかという判定が必要になります。
同じ木に属している場合ループができるのでこれを防ぐ必要があります。
この時、効率よく判定するデータ構造としてUnion Find木というのが使われます。
簡単にいうと木の根(ルート)が同じだと同じ木だと判断するという考えです。class UnionTree { List<int> par; public UnionTree(int n) { par = new List<int>(n); for (int i=0;i<n;i++) { par.Add(i); } } public int root(int x) { if (par[x] == x) { return x; } else { return par[x] = root(par[x]); } } public bool same(int x, int y) { return root(x) == root(y); } public void unite(int x, int y) { x = root(x); y = root(y); if (x == y) return; par[x] = y; } }上記のコードの
List<int> par
はiの親ノードを表していてます。言い換えるとi番目のノードの親はpar[i]ということです。
same()
は親ノードを辿って同じルートに行き着くなら同じ木という判断をします。
unite
は同じ根を持つ木をつなげます。辺の表現
IComparable
を実装することによって比較できるようにします。class Edge : IComparable { public int u, v, cost; public Edge(int u, int v, int cost) { this.u = u; this.v = v; this.cost = cost; } public int CompareTo(object obj) { return cost.CompareTo((obj as Edge).cost); } }クラスカル法の実装
edge.Sort()
することによって辺を重みごとに並べます。
あとは辺を重みが低い順に追加していきますが、頂点が同じ木に属している時は追加しません。public static int kruskar(List<Edge> edge,int n) { edge.Sort(); var union = new UnionTree (n); int w = 0; for (int i=0; i<n; i++) { Edge e = edge[i]; if (!union.same(e.u, e.v)) { union.unite(e.u, e.v); w += e.cost; } } return w; }コードの全景です。
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace SpanningTree { class UnionTree { List<int> par; public UnionTree(int n) { par = new List<int>(n); for (int i=0;i<n;i++) { par.Add(i); } } public int root(int x) { if (par[x] == x) { return x; } else { return par[x] = root(par[x]); } } public bool same(int x, int y) { return root(x) == root(y); } public void unite(int x, int y) { x = root(x); y = root(y); if (x == y) return; par[x] = y; } } class Edge : IComparable { public int u, v, cost; public Edge(int u, int v, int cost) { this.u = u; this.v = v; this.cost = cost; } public int CompareTo(object obj) { return cost.CompareTo((obj as Edge).cost); } } class Program { public static int kruskar(List<Edge> edge,int n) { edge.Sort(); var union = new UnionTree (n); int w = 0; for (int i=0; i<n; i++) { Edge e = edge[i]; if (!union.same(e.u, e.v)) { union.unite(e.u, e.v); w += e.cost; } } return w; } static void Main(string[] args) { string line = Console.ReadLine(); var vals = line.Split(' '); int E = Int32.Parse(vals[1]); List<Edge> edge = new List<Edge>(); for (int i=0;i<E;i++) { line = Console.ReadLine(); vals = line.Split(' '); int s = Int32.Parse(vals[0]); int t = Int32.Parse(vals[1]); int w = Int32.Parse(vals[2]); Edge e = new Edge(s,t,w); edge.Add(e); } int c = kruskar(edge, E); Console.WriteLine(c); } } }