TES Blog

株式会社テクニカルエンジニアリングサポートに所属する社員が、自身が携わるテクノロジーやイベントに関する情報を発信しています。

C# .NET Framework によるRS232C通信

はじめに

普段案件としてWebアプリケーション開発に携わることが多いですが、最近関わった案件にてRS232C通信を用いた開発を行いましたので、備忘の意味合いも込めて記事にしました。

開発環境

  • Windows 10 Pro
  • Visual Studio 2017
  • C# .NET Framework 4.5

開発準備

コントロールの要素として SerialPort を用意して、マシンに接続されているCOMを参照することになりますが、開発時に通信状況を確認するために仮想シリアルポートを用意すると、効率よく開発ができると思います。
今回の作業時には、com0comを利用しました。
こちらを用いることで、マシン内に仮想シリアルポートを用意して、WindowsFormのアプリケーションにてCOMを認識することができます。

データの受信

機器から送信されるコマンドを受信する場合については、下記のコードで実装可能です。

ポートのオープン

通信を行う前に、対象のシリアルポートのオープンを行います。

try
{
    this.serialPort.PortName = "COM4";
    this.serialPort.Open();
}
catch (Exception ex)
{
     Console.WriteLine(ex.ToString());
}

受信処理

RS232Cのポートに対するデータの受信処理は SerialPortDataReceived イベントハンドラを使用します。

private void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    // シリアルポートをオープンしていない場合、処理を行わない.
    if (!this.serialPort.IsOpen) return;

    try
    {
        // 受信データを読み込む.
        string receivedData = this.serialPort.ReadExisting();
        Console.WriteLine(receivedData);
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.ToString());
    }
}

フォームの要素(LabelTextBox 等)に受信した文字列を表示する場合ですが、フォームを管理するスレッドとDataReceivedによるデータ受信を管理するスレッドは異なるため、delegate を使用して実装します。

private delegate void ShowDataDelegate();

private void SetTextBox(string data)
{
    this.textBox.Text = data;
}

private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    // シリアルポートをオープンしていない場合、処理を行わない.
    if (!this.serialPort.IsOpen) return;

    try
    {
        // 受信データを読み込む.
        string receivedData = this.serialPort.ReadExisting();
        Console.WriteLine(receivedData);
        
        ShowDataDelegate showData = new ShowDataDelegate(SetTextBox);
        this.textBox.Invoke(showData, receivedData);
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.ToString());
    }
}

データの送信

機器に対するコマンドを送信する場合については、下記のコードで実装可能です。

ポートのオープン

送信時も受信時と同様にポートのオープンを行います。

送信処理

送信を行う場合、SerialPortWriteメソッドを使用します。
ポイントとなるのは、送信対象の機器において改行コードの扱いが異なりますので、適宜調整が必要です。

string command = "sample code";
this.serialPort.Write(command + "\r\n");
// this.serialPort.Write(command + "\r");

単体のコマンド発行であれば上記で問題ありませんが、複数同時にコマンドを発行する場合には、書き込みに失敗するケースを考えてリトライ処理を実装すると、精度向上が見込めます。

private async void WriteSerialPort(string command)
{
    int retry = 0;

    try
    {
        this.serialPort.Write(command + "\r\n");
    }
    catch (IOException ex)
    {
        await Task.Delay(300);
        retry += 1;

        if (retry > 5) throw ex;
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.ToString());
    }
}

選択可能なポートの取得

接続されているポート一覧を取得するには、SerialPortGetPortNamesメソッドを使用します。
コンボボックスから選択できるように要素に一覧を設定する場合は、以下のコードで実装可能です。

private void InitializeSerialPort()
{
    DataTable ports = new DataTable();
    ports.Columns.Add("key", typeof(string));
    ports.Columns.Add("value", typeof(string));

    foreach (string name in SerialPort.GetPortNames())
    {
        DataRow row = ports.NewRow();
        row["key"] = name;
        row["value"] = name;
        ports.Rows.Add(row);
    }

    ports.AcceptChanges();

    this.cmbSerialPort.ValueMember = "key";
    this.cmbSerialPort.DisplayMember = "value";
    this.cmbSerialPort.DataSource = ports;
}

jQuery を使わずに、記事のシェア数を表示するソーシャルパーツをフラットデザインっぽくカスタマイズする

はじめに

TES で Web エンジニアをしている Hayato Yamashita です。

今回は、はてなブログのソーシャルパーツをフラットデザインっぽくカスタマイズする方法を紹介します。

カスタマイズ後の見た目

こんな感じの見た目になります。
こういうカスタマイズをしたい、どうやってカスタマイズするのか知りたい、という方は本記事をご覧ください。

f:id:h-yamashita:20180402135652p:plain

この記事のポイント

  • ソーシャルパーツをフラットデザインっぽくカスタマイズできる
    • コピペで使える!
  • はてなブックマークと Facebook のシェア数を表示できる
    • jQuery を使わず IE11 対応!
  • 簡単なコード解説付き
    • 理解しやすいかも
続きを読む

jQuery を使わずに、はてなブログの外部参照リンクを target="_blank" にする方法

はじめに

TES で Web エンジニアをしている Hayato Yamashita です。

最近 TES では、外部情報発信の取り組みとして TES Blog を開設しました。
既にいくつか記事をあげていますので、良かったら他の記事も読んでみてください。

記事一覧 - TES Blog

さて、その開設にあたって私の方でいくつか設定をしていたのですが、社員より以下の要望をもらいました。

href の飛び先を別タブにすることは可能?

こちらの方法を調べましたので、記事として共有します。

続きを読む

外部公開サーバがブルートフォース攻撃されているか確認する

こんにちは。インフラの業務をさせて頂いている者です。

だんだん春らしく暖かくなってきましたね。
花粉症の方はこれから一緒に頑張りましょう!

さて、今回は…

f:id:manabkr:20180314160410j:plain

 外部公開しているサーバにブルートフォース攻撃がされているかチェックしてみたい

…と思います。

対象となる読者

  • 外部公開のWebサーバを立ててみたけど何をしたらいいのか分からない方
  • 自身のサーバにどんなSSHブルートフォース攻撃がされているか確認したい方
続きを読む

TwitterAPIで使うアクセストークンが勝手に消えたお話

Twitter APIとの連携で、Twitter Application Managementでトークンを発行して自分のアプリケーションで利用することは多いと思う。

私もTwitter APIを利用してTwitterのBotを作っていたのですが、アプリケーション環境で突如Twitterとの接続でエラーが出るようになった。

Spring Boot エラー内容

2018-02-11T20:14:14.911250+00:00 app[web.1]: org.springframework.web.client.ResourceAccessException: I/O error on POST request for "https://api.twitter.com/1.1/statuses/update.json": cannot retry due to server authentication, in streaming mode; nested exception is java.net.HttpRetryException: cannot retry due to server authentication, in streaming mode

エラー内容でググってみたら、 callbackUrl を設定したら直るとあったので試してみたがダメ…。

解決方法

色々見てる内に、Twitter Application ManagementKeys and Access Tokens 画面でアクセストークンが消えてることに気がついた。 再度取得し直して、アプリケーション上のトークンを更新してあげたらちゃんと動くようになった。

アクセストークンの再追加時にエラーメッセージで「既に存在するぞ!!」って何故か怒られるが、新しいアクセストークンが発行される。 以前使用していたアクセストークンとは別のものになっているため、アプリケーションで使用していたトークンの更新を忘れないようにすること。

もし同じような状況になったら、アクセストークンが消えていないか確認してみてください。

サーバー環境にある権限のついたファイルをローカル環境にコピーする方法

nginxのログファイルをサーバーからローカル環境に持ってこようとした時に、 Permission denied でエラーとなってしまったのでその時に行なった対策を載せます。

下記参考にさせていただきました。ありがとうございます!!

sshでやる

コピー対象のファイル内容が、ローカル環境で指定したファイルにコピーされます。

ssh -t {{ ホスト名 }} "echo {{ sudo password }} | sudo -S cat /var/log/nginx/access.log" > {{ ローカル側のコピー先ファイル }}

※ 上記コマンドでは echo コマンドによりパスワードの文字列が履歴に残ってしまうため、セキュリティリスクが高まります。利用には細心の注意が必要です。

scpでやる

1.対象のファイルをホームディレクトリにコピー

安全に作業を行うため、一旦ホームディレクトリにコピーする。

ssh {{ ホスト名 }}
sudo cp /var/log/nginx/access.log ~/

2.所有者の変更

ホームディレクトリにコピーしたファイルの権限を自分に書き換える。

# ユーザー名確認
whoami
# 所有者の変更
sudo chown {{ ユーザー名 }} access.log

3.SCPでサーバーからローカルに持ってくる

権限を変更したファイルを、ローカル環境の適当なディレクトリにファイルごとコピーする。

scp {{ ユーザー名 }}@{{ ホスト名 }}:~/access.log {{ ローカルディレクトリ }}

4.ホームディレクトリにコピーしたファイルを削除

コピーが終わったら、ホームティレクトリにコピーしたファイルは不要なので削除する。

rm access.log

Gitコマンドあれこれ

個人的に忘れっぽいコマンドとか、あまり普段使わないようなコマンドを備忘録として載せます。

git rebaseの使い方

コンフリクト解消した後どうするんだっけ…ってたまになる。

1.マスターを最新化する

git checkout master
git pull

2.トピックブランチにリベースする

git checkout {{ トピックブランチ名 }}
git rebase master

3.リベースした時にコンフリクトが発生時

# コンフリクトを解消
git add .
git rebase --continue

4.コンフリクト解消後すでにリモートにpushしてある時

# リベースコンテニュー後に下記を実行
git push -f origin {{ リモートブランチ名 }}

※force pushなので気をつけること

Git Stashの使い方(編集内容一時退避)

編集内容を退避させる

git stash save

※saveは省略可能

退避した内容の復活と、復活させたstash内容の削除を同時に行う

git stash pop stash@{0}

※最新の退避内容を復活&削除したい場合は stash@{0} が不要

複数行のコミットコメントを行う

git commit -F- <<EOM
> コミットコメント要約
>
> コミットコメント詳細
> 詳細あれこれ
> EOM

対象ブランチ間同士の差分系

こんなに差分取ることなんて早々ない。

差分のあるファイルを対象に、ファイル名だけを取得

git diff {{ ブランチ名1 }} {{ ブランチ名2 }}  --name-only

差分の種類を取得(追加・更新・削除など)

git diff --name-status {{ ブランチ名1 }} {{ ブランチ名2 }}

git logの表示形式で差分を取得

git log -p {{ ブランチ名1 }}...{{ ブランチ名2 }}

コミットハッシュ値とコミットコメントのみの差分を取得

git log --pretty=format:"%H %s" {{ ブランチ名1 }}...{{ ブランチ名2 }}

ソースレベルでブランチ同士の差分を取得

git diff {{ ブランチ名1 }} {{ ブランチ名2 }}

空コミットを行ってPRを作成する

プルリク駆動で便利!

1.--allow-emptyで空のコミットを作成

git commit --allow-empty -m "PR作成用空コミット"

2.通常どおりpushする

3.空コミットでpushされたブランチでPRを作成

4.その後、コミットしたい部分をaddする

5.次に変更を行った部分をコミットする場合、--amendで空コミットを上書き

git commit --amend -v

6.force pushで空コミットしたブランチに対応した内容を反映させる

git push -f origin {{ リモートブランチ名 }}

※force pushなので気をつけること

指定ファイルをgitの追跡対象から外す

1.除外する

git update-index --assume-unchanged {{ ファイルパス }}

2.除外を解除する

git update-index --no-assume-unchanged {{ ファイルパス }}

3.除外しているファイルを確認する

git ls-files -v | grep ^h

直前のコミット取り消し

コミットの取り消しとワークディレクトリの編集内容も削除

git reset --hard HEAD^

ワークディレクトリの内容はそのままでコミットだけ取り消し

git reset --soft HEAD^

※ステージングに上げた状態(addした状態)になる

そこからadd状態を取り消すなら

git reset

cherry-pickの使い方

コミット単位でcherry-pick

単一のコミット内容のみ反映する。

git cherry-pick 1 {{ コミット番号 }}

マージコミット単位でcherry-pick

-m オプションを使用する。

git cherry-pick -m 1 {{ マージコミット番号 }}

マージ単位となるので、例えば一つのPRに複数件のコミットがある場合は、すべてのコミット内容が反映対象になります。