// --------------------------------------------------
// Global Versatile Controler http://www.gvc-on.net/
// --------------------------------------------------
// --------------------------------------------------
// Revision Memo (Y.M.D Editor/Memo)
// --------------------------------------------------
//
// 2013.06.12 メッセージキュー部分の実装(移植)をする
//
// 2013.06.10 T.Kabu
// 汎用制御装置 Grobal Versatile Controller Daemon (gvcd)
//
// gvcd /dev/????? (GVCが接続されているデバイス名)
//
// デバイスのパラメータは9600N81
// 9600bps
// ノンパリティ
// 8ビット
// ストップビット1
// フロー制御はArduinoではしていないのでOFF
//
// パラメータはsetserialなどの外部コマンドで設定すればいいとおもう
//
// sync;gcc -O2 -Wall -lm ./gvcd.c -o gvcd
//
// Fedora18 では、gcc -O2 -Wall -fno-strict-aliasing ./gvcd_20130625.c -o gvcd、として
// コンパイルしないと、dereferencing type-punned pointer(型またぎすぎみたいな)感じで怒られる。
//
// 参考URLいろいろ
// http://pinka99.ddo.jp/nanao/work/daemon.html
// http://d.hatena.ne.jp/rero/20041002/p1
// http://linuxmag.sourceforge.jp/Japanese/March2003/article287.shtml
// http://www.geocities.co.jp/Athlete-Samos/7760/study/msgkyu1.html
// http://www.geocities.jp/taka_owl2005/job/UNIX/kernel/ipc.html
// http://d.hatena.ne.jp/ka2yan/20090327
//
// ------------------------------
// BASE
// ------------------------------
// 2011.11.02 T.Kabu gvcd とりあえず取り掛かる
// 2011.12.01 T.Kabu gvcd2c 幾つかのセンサーに対応して画面に吐き出すようにした
// 2011.12.20 T.Kabu gvcd3 デーモン化、プロセスチェック、ログ吐き出しに取り掛かる
// 2012.02.02 T.Kabu gvcd3b テストソースからあれこれマージ、プロセス間通信(メッセージキュー)対応
// 2012.02.06 T.Kabu gvcd3c GVCに対してコマンド送信
// 2012.03.09 T.Kabu gvcd4 スタートフレームと言う定義をやめて、デリミタメッセージにした
// 2013.06.10 T.Kabu gvcd_20130610 Rev.2用に色々修正
// 2013.07.18 T.Kabu gvcd_20130717 赤外線データ(つまりリモコン)の送受信保存再送が出来るようになったのでいったんFix
// 2013.12.20 T.Kabu 清書と、赤外線データのサイズの関係で扱えるデータサイズをヘッダ込みで最大1600バイトに統一する
//---------------------------------------------------
// include
//---------------------------------------------------
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <syslog.h>
#include <termios.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/ipc.h>
#include <sys/msg.h>
///#include <linux/ipc.h>
///#include <linux/msg.h>
#include <errno.h>
#include "gvcd.h"
// --------------------------------------------------
// Const Define
// --------------------------------------------------
// --------------------------------------------------
// Structure
// --------------------------------------------------
// --------------------------------------------------
// Prototype Define
// --------------------------------------------------
// ------------------------------
// GVCキュー処理 (main関数の中でのキュー処理テーブル初期化を忘れずに)
// ------------------------------
int gvc_q_job_dummy(void * q_po); // キューダミー処理
int gvc_q_job_version(void * q_po); // 0x01:バージョン要求
int gvc_q_job_modulelist(void * q_po); // 0x02:モジュール一覧要求
int gvc_q_job_moduledata(void * q_po); // 0x03:モジュールデータ要求
int gvc_q_job_switchoff(void * q_po); // 0x20:スイッチOFF要求
int gvc_q_job_switchon(void * q_po); // 0x21:スイッチON要求
int gvc_q_job_switchstatus(void * q_po); // 0x2f:スイッチ状態要求
int gvc_q_job_masterreset(void * q_po); // 0x7e:マスターコントローラーリセット要求
int gvc_q_job_masterrestart(void * q_po); // 0x7e:マスターコントローラーリスタート要求
int gvc_q_job_masterstop(void * q_po); // 0x7f:マスターコントローラーストップ要求
///int gvc_q_job_lcdoutput(void * q_po); // 0x81:LCDデータ出力要求
int gvc_q_job_irtx(void * q_po); // 0x91:リモコンデータ送信要求
int gvc_q_job_irrx(void * q_po); // 0x92:リモコンデータ受信要求
int gvc_q_job_irset(void * q_po); // 0x93:リモコンデータ設定要求
int gvc_q_job_irget(void * q_po); // 0x94:リモコンデータ取得要求
int gvc_q_job_irdel(void * q_po); // 0x95:リモコンデータ削除要求
///int gvc_q_job_voiceoutput(void * q_po); // 0xa1:音声合成データ出力要求
int gvc_q_job_daemonstop(void * q_po); // 0xff:gvcdストップ要求
// ------------------------------
// GVCメッセージ処理 (main関数の中でのメッセージ処理テーブル初期化を忘れずに)
// ------------------------------
int gvc_msg_job_dummy(void * msg_po); // メッセージダミー処理
int gvc_msg_job_delimiterframe(void * msg_po); // デリミタメッセージ
//int gvc_msg_job_a(void * msg_po); // TBD
//int gvc_msg_job_b(void * msg_po); // TBD
//int gvc_msg_job_c(void * msg_po); // TBD
int gvc_msg_job_distance(void * msg_po); // 距離
//int gvc_msg_job_e(void * msg_po); // TBD
//int gvc_msg_job_f(void * msg_po); // TBD
//int gvc_msg_job_g(void * msg_po); // TBD
int gvc_msg_job_humidity(void * msg_po); // 湿度
int gvc_msg_job_ir(void * msg_po); // 赤外線
//int gvc_msg_job_j(void * msg_po); // TBD
//int gvc_msg_job_k(void * msg_po); // TBD
int gvc_msg_job_light(void * msg_po); // 照度
//int gvc_msg_job_m(void * msg_po); // TBD
//int gvc_msg_job_n(void * msg_po); // TBD
//int gvc_msg_job_o(void * msg_po); // TBD
int gvc_msg_job_pressure(void * msg_po); // 大気圧
//int gvc_msg_job_q(void * msg_po); // TBD
//int gvc_msg_job_r(void * msg_po); // TBD
//int gvc_msg_job_s(void * msg_po); // TBD
int gvc_msg_job_temperature(void * msg_po); // 気温
//int gvc_msg_job_u(void * msg_po); // TBD
//int gvc_msg_job_v(void * msg_po); // TBD
//int gvc_msg_job_w(void * msg_po); // TBD
//int gvc_msg_job_x(void * msg_po); // TBD
//int gvc_msg_job_y(void * msg_po); // TBD
//int gvc_msg_job_z(void * msg_po); // TBD
int gvc_msg_job_other(void * msg_po); // その他
void signal_alarm(); // ALARMシグナル処理
void signal_sighup(); // SIGHUPシグナル処理
void put_log(int, char * logstr); // ログ出力
// --------------------------------------------------
// Variable Param
// --------------------------------------------------
char daytime_str[DAYTIME_LEN]; // 日時文字列 2011/10/14 12:43:58
int gvc_port; // GVCを接続しているポート(/dev/ttyUSB0とか)
int gvcd_mode = 0; // GVCD動作モード 0:通常モード 1:ログファイル別出力モード 99:ダンプモード
int gvc_log_fp; // GVCログファイルポインタ
// GVCキュー処理テーブル(戻り値:int、メッセージそのものは(void *)に型キャストして渡す(メッセージの中身はそれぞれ異なるため)
int (*gvc_queue_job[0x100])(void * q_po);
// GVCメッセージ処理テーブル(戻り値:int、メッセージそのものは(void *)に型キャストして渡す(メッセージの中身はそれぞれ異なるため)
int (*gvc_msg_job[0x100])(void * msg_po);
// デリミタメッセージ
static char GVC_DELIMITER_MSG[] = {
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xab, 0xaa
};
// コマンド送信可能状態(0:デリミタ待ち、1:コマンド送信可能)
int gvc_cmd_ready = 0;
// 受信バッファ
unsigned char rx_buffer[BUFF_SIZE];
// 送信バッファ
unsigned char tx_buffer[BUFF_SIZE];
// 赤外線データ格納用ファイル
FILE *datafp; // データ格納用ファイルポインタ
char datafp_flag; // データ格納フラグ(0:None, 1:Wait, 2:Complete, etc)
// --------------------------------------------------
// Sub Routine
// --------------------------------------------------
// ------------------------------------------
// Sub Routine/GVCキュー処理
// ------------------------------------------
// --------------------------------
// GVCキュー処理:ダミー
// --------------------------------
int gvc_q_job_dummy(void * q_po)
{
// ----------------
// ローカル変数定義
// ----------------
char logstr[BUFF_SIZE];
GVC_MESSAGE_QUEUE_t * gvc_message_queue; // GVC メッセージキュー用ポインタ(キューデータにかぶせる)
// キューポインタにGVC_MESSAGE_QUEUE_tをかぶせる
gvc_message_queue = (GVC_MESSAGE_QUEUE_t *)q_po;
// ログ出力用文字列を生成
sprintf(logstr, "QUEUE DUMMY : qtype=%lu, gvc_num=%d, msg_type=0x%02x, dev_num=0x%02x, format=0x%02x, cmd/result=0x%02x, data_len=0x%02x",
gvc_message_queue->qtype,
gvc_message_queue->q.gvc_num,
gvc_message_queue->q.msg_type,
gvc_message_queue->q.dev_num,
gvc_message_queue->q.format,
gvc_message_queue->q.cmd,
gvc_message_queue->q.data_len
);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
return 0;
}
// --------------------------------
// GVCキュー処理:0x01:バージョン要求
// --------------------------------
int gvc_q_job_version(void * q_po)
{
// ----------------
// ローカル変数定義
// ----------------
char logstr[BUFF_SIZE];
GVC_MESSAGE_QUEUE_t * gvc_message_queue; // GVC メッセージキュー用ポインタ(キューデータにかぶせる)
/// GVC_SERIAL_MESSAGE_t * gvc_serial_message; // GVC シリアルメッセージ用ポインタ(シリアルデータにかぶせる)
int tx_len = 0; // 送信できたデータの長さ
// キューポインタにGVC_MESSAGE_QUEUE_tをかぶせる
gvc_message_queue = (GVC_MESSAGE_QUEUE_t *)q_po;
// ----------------
// GVCに対してコマンド送信
// ----------------
// 送信バッファにキューメッセージ部分をコピー
// メッセージキュー、というかLinuxレベルになるとテーブル構造体のアラインメントが行われるから注意すること!!
/// memcpy(tx_buffer, (void *)&(gvc_message_queue->q.msg_type), GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len);
// 送信バッファにGVC_SERIAL_MESSAGE_tをかぶせる
/// gvc_serial_message = (GVC_SERIAL_MESSAGE_t *)tx_buffer;
// ↑とかはできない!! ヽ(`Д´#)ノ ムキー!!
tx_buffer[0] = gvc_message_queue->q.msg_type; // gvc_serial_message->msg_type
tx_buffer[1] = gvc_message_queue->q.dev_num; // gvc_serial_message->dev_num
tx_buffer[2] = gvc_message_queue->q.format; // gvc_serial_message->format
tx_buffer[3] = gvc_message_queue->q.cmd; // gvc_serial_message->cmd
*(int *)&(tx_buffer[4]) = gvc_message_queue->q.data_len; // gvc_serial_message->data_len
memcpy((void *)&(tx_buffer[6]), gvc_message_queue->q.data, GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len);
// CRCを計算して、メッセージの最後に設定
/// gvc_serial_message->data[ GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_serial_message->data_len ] = GetCRC8((void *)gvc_serial_message, GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_serial_message->data_len);
tx_buffer[ GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len ] = GetCRC8((void *)tx_buffer, GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len);
// ↑データを送信する側は、データのCRCを計算したあとで
// そのCRCをデータの最後に連結して相手に送ればいい
// シリアルポートへのライト(checksumまで送信するので長さは+1される)
tx_len = write(gvc_port, (void *)tx_buffer, GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len + 1);
// きちんと送信できていないなら
if (tx_len < 0)
{
// もし割り込みによる中断だったら
if (errno == EINTR)
{
// LOGメッセージ設定
sprintf(logstr, "WRITE is EINTR. tx_len=%d, errno=%d", tx_len, errno);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
// それ以外の場合には
else
{
// LOGメッセージ設定
sprintf(logstr, "WRITE is OTHER ERROR !? tx_len=%d, errno=%d", tx_len, errno);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
}
// 送信したデータ長が実際と合致しないなら
else if (tx_len != (GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len + 1))
{
// LOGメッセージ設定
sprintf(logstr, "WRITE is SHORT or LONG!? tx_len=%d, org_len=%d", tx_len, (GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len + 1));
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
// きちんと送信できたなら
else
{
// ログ出力用文字列を生成
sprintf(logstr, "QUEUE VERSION : qtype=%lu, gvc_num=%d, msg_type=0x%02x, dev_num=0x%02x, format=0x%02x, cmd/result=0x%02x, data_len=0x%02x",
gvc_message_queue->qtype,
gvc_message_queue->q.gvc_num,
gvc_message_queue->q.msg_type,
gvc_message_queue->q.dev_num,
gvc_message_queue->q.format,
gvc_message_queue->q.cmd,
gvc_message_queue->q.data_len
);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
// 送信できたバイト数を返す
return tx_len;
}
// --------------------------------
// GVCキュー処理:0x02:モジュール一覧要求
// --------------------------------
int gvc_q_job_modulelist(void * q_po)
{
// ----------------
// ローカル変数定義
// ----------------
char logstr[BUFF_SIZE];
GVC_MESSAGE_QUEUE_t * gvc_message_queue; // GVC メッセージキュー用ポインタ(キューデータにかぶせる)
int tx_len = 0; // 送信できたデータの長さ
// キューポインタにGVC_MESSAGE_QUEUE_tをかぶせる
gvc_message_queue = (GVC_MESSAGE_QUEUE_t *)q_po;
// ----------------
// GVCに対してコマンド送信
// ----------------
// 送信バッファにキューメッセージ部分をコピー
tx_buffer[0] = gvc_message_queue->q.msg_type; // gvc_serial_message->msg_type
tx_buffer[1] = gvc_message_queue->q.dev_num; // gvc_serial_message->dev_num
tx_buffer[2] = gvc_message_queue->q.format; // gvc_serial_message->format
tx_buffer[3] = gvc_message_queue->q.cmd; // gvc_serial_message->cmd
*(int *)&(tx_buffer[4]) = gvc_message_queue->q.data_len; // gvc_serial_message->data_len
memcpy((void *)&(tx_buffer[6]), gvc_message_queue->q.data, GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len);
// CRCを計算して、メッセージの最後に設定
tx_buffer[ GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len ] = GetCRC8((void *)tx_buffer, GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len);
// ↑データを送信する側は、データのCRCを計算したあとで
// そのCRCをデータの最後に連結して相手に送ればいい
// シリアルポートへのライト(checksumまで送信するので長さは+1される)
tx_len = write(gvc_port, (void *)tx_buffer, GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len + 1);
// きちんと送信できていないなら
if (tx_len < 0)
{
// もし割り込みによる中断だったら
if (errno == EINTR)
{
// LOGメッセージ設定
sprintf(logstr, "WRITE is EINTR. tx_len=%d, errno=%d", tx_len, errno);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
// それ以外の場合には
else
{
// LOGメッセージ設定
sprintf(logstr, "WRITE is OTHER ERROR !? tx_len=%d, errno=%d", tx_len, errno);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
}
// 送信したデータ長が実際と合致しないなら
else if (tx_len != (GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len + 1))
{
// LOGメッセージ設定
sprintf(logstr, "WRITE is SHORT !? tx_len=%d, org_len=%d", tx_len, (GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len + 1));
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
// きちんと送信できたなら
else
{
// ログ出力用文字列を生成
sprintf(logstr, "QUEUE MODULE LIST : qtype=%lu, gvc_num=%d, msg_type=0x%02x, dev_num=0x%02x, format=0x%02x, cmd/result=0x%02x, data_len=0x%02x",
gvc_message_queue->qtype,
gvc_message_queue->q.gvc_num,
gvc_message_queue->q.msg_type,
gvc_message_queue->q.dev_num,
gvc_message_queue->q.format,
gvc_message_queue->q.cmd,
gvc_message_queue->q.data_len
);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
return 0;
}
// --------------------------------
// GVCキュー処理:0x03:モジュールデータ要求
// --------------------------------
int gvc_q_job_moduledata(void * q_po)
{
// ----------------
// ローカル変数定義
// ----------------
char logstr[BUFF_SIZE];
GVC_MESSAGE_QUEUE_t * gvc_message_queue; // GVC メッセージキュー用ポインタ(キューデータにかぶせる)
// キューポインタにGVC_MESSAGE_QUEUE_tをかぶせる
gvc_message_queue = (GVC_MESSAGE_QUEUE_t *)q_po;
// ログ出力用文字列を生成
sprintf(logstr, "QUEUE MODULE DATA : qtype=%lu, gvc_num=%d, msg_type=0x%02x, dev_num=0x%02x, format=0x%02x, cmd/result=0x%02x, data_len=0x%02x",
gvc_message_queue->qtype,
gvc_message_queue->q.gvc_num,
gvc_message_queue->q.msg_type,
gvc_message_queue->q.dev_num,
gvc_message_queue->q.format,
gvc_message_queue->q.cmd,
gvc_message_queue->q.data_len
);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
// GVCに対してコマンド送信
return 0;
}
// --------------------------------
// GVCキュー処理:0x20:スイッチOFF要求
// --------------------------------
int gvc_q_job_switchoff(void * q_po)
{
// ----------------
// ローカル変数定義
// ----------------
char logstr[BUFF_SIZE];
GVC_MESSAGE_QUEUE_t * gvc_message_queue; // GVC メッセージキュー用ポインタ(キューデータにかぶせる)
// キューポインタにGVC_MESSAGE_QUEUE_tをかぶせる
gvc_message_queue = (GVC_MESSAGE_QUEUE_t *)q_po;
int tx_len = 0; // 送信できたデータの長さ
// ----------------
// GVCに対してコマンド送信
// ----------------
// 送信バッファにキューメッセージ部分をコピー
tx_buffer[0] = gvc_message_queue->q.msg_type; // gvc_serial_message->msg_type
tx_buffer[1] = gvc_message_queue->q.dev_num; // gvc_serial_message->dev_num
tx_buffer[2] = gvc_message_queue->q.format; // gvc_serial_message->format
tx_buffer[3] = gvc_message_queue->q.cmd; // gvc_serial_message->cmd
*(int *)&(tx_buffer[4]) = gvc_message_queue->q.data_len; // gvc_serial_message->data_len
memcpy((void *)&(tx_buffer[6]), gvc_message_queue->q.data, GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len);
// CRCを計算して、メッセージの最後に設定
tx_buffer[ GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len ] = GetCRC8((void *)tx_buffer, GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len);
// ↑データを送信する側は、データのCRCを計算したあとで
// そのCRCをデータの最後に連結して相手に送ればいい
// シリアルポートへのライト(checksumまで送信するので長さは+1される)
tx_len = write(gvc_port, (void *)tx_buffer, GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len + 1);
// きちんと送信できていないなら
if (tx_len < 0)
{
// もし割り込みによる中断だったら
if (errno == EINTR)
{
// LOGメッセージ設定
sprintf(logstr, "WRITE is EINTR. tx_len=%d, errno=%d", tx_len, errno);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
// それ以外の場合には
else
{
// LOGメッセージ設定
sprintf(logstr, "WRITE is OTHER ERROR !? tx_len=%d, errno=%d", tx_len, errno);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
}
// 送信したデータ長が実際と合致しないなら
else if (tx_len != (GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len + 1))
{
// LOGメッセージ設定
sprintf(logstr, "WRITE is SHORT !? tx_len=%d, org_len=%d", tx_len, (GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len + 1));
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
// きちんと送信できたなら
else
{
// ログ出力用文字列を生成
sprintf(logstr, "QUEUE SWITCH OFF : qtype=%lu, gvc_num=%d, msg_type=0x%02x, dev_num=0x%02x, format=0x%02x, cmd/result=0x%02x, data_len=0x%02x",
gvc_message_queue->qtype,
gvc_message_queue->q.gvc_num,
gvc_message_queue->q.msg_type,
gvc_message_queue->q.dev_num,
gvc_message_queue->q.format,
gvc_message_queue->q.cmd,
gvc_message_queue->q.data_len
);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
return 0;
}
// --------------------------------
// GVCキュー処理:0x21:スイッチON要求
// --------------------------------
int gvc_q_job_switchon(void * q_po)
{
// ----------------
// ローカル変数定義
// ----------------
char logstr[BUFF_SIZE];
GVC_MESSAGE_QUEUE_t * gvc_message_queue; // GVC メッセージキュー用ポインタ(キューデータにかぶせる)
int tx_len = 0; // 送信できたデータの長さ
// キューポインタにGVC_MESSAGE_QUEUE_tをかぶせる
gvc_message_queue = (GVC_MESSAGE_QUEUE_t *)q_po;
// ----------------
// GVCに対してコマンド送信
// ----------------
// 送信バッファにキューメッセージ部分をコピー
tx_buffer[0] = gvc_message_queue->q.msg_type; // gvc_serial_message->msg_type
tx_buffer[1] = gvc_message_queue->q.dev_num; // gvc_serial_message->dev_num
tx_buffer[2] = gvc_message_queue->q.format; // gvc_serial_message->format
tx_buffer[3] = gvc_message_queue->q.cmd; // gvc_serial_message->cmd
*(int *)&(tx_buffer[4]) = gvc_message_queue->q.data_len; // gvc_serial_message->data_len
memcpy((void *)&(tx_buffer[6]), gvc_message_queue->q.data, GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len);
// CRCを計算して、メッセージの最後に設定
tx_buffer[ GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len ] = GetCRC8((void *)tx_buffer, GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len);
// ↑データを送信する側は、データのCRCを計算したあとで
// そのCRCをデータの最後に連結して相手に送ればいい
// シリアルポートへのライト(checksumまで送信するので長さは+1される)
tx_len = write(gvc_port, (void *)tx_buffer, GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len + 1);
// きちんと送信できていないなら
if (tx_len < 0)
{
// もし割り込みによる中断だったら
if (errno == EINTR)
{
// LOGメッセージ設定
sprintf(logstr, "WRITE is EINTR. tx_len=%d, errno=%d", tx_len, errno);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
// それ以外の場合には
else
{
// LOGメッセージ設定
sprintf(logstr, "WRITE is OTHER ERROR !? tx_len=%d, errno=%d", tx_len, errno);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
}
// 送信したデータ長が実際と合致しないなら
else if (tx_len != (GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len + 1))
{
// LOGメッセージ設定
sprintf(logstr, "WRITE is SHORT !? tx_len=%d, org_len=%d", tx_len, (GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len + 1));
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
// きちんと送信できたなら
else
{
// ログ出力用文字列を生成
sprintf(logstr, "QUEUE SWITCH ON : qtype=%lu, gvc_num=%d, msg_type=0x%02x, dev_num=0x%02x, format=0x%02x, cmd/result=0x%02x, data_len=0x%02x",
gvc_message_queue->qtype,
gvc_message_queue->q.gvc_num,
gvc_message_queue->q.msg_type,
gvc_message_queue->q.dev_num,
gvc_message_queue->q.format,
gvc_message_queue->q.cmd,
gvc_message_queue->q.data_len
);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
return 0;
}
// --------------------------------
// GVCキュー処理:0x2f:スイッチ状態要求
// --------------------------------
int gvc_q_job_switchstatus(void * q_po)
{
// ----------------
// ローカル変数定義
// ----------------
char logstr[BUFF_SIZE];
GVC_MESSAGE_QUEUE_t * gvc_message_queue; // GVC メッセージキュー用ポインタ(キューデータにかぶせる)
// キューポインタにGVC_MESSAGE_QUEUE_tをかぶせる
gvc_message_queue = (GVC_MESSAGE_QUEUE_t *)q_po;
// ログ出力用文字列を生成
sprintf(logstr, "QUEUE SWITCH STATUS : qtype=%lu, gvc_num=%d, msg_type=0x%02x, dev_num=0x%02x, format=0x%02x, cmd/result=0x%02x, data_len=0x%02x",
gvc_message_queue->qtype,
gvc_message_queue->q.gvc_num,
gvc_message_queue->q.msg_type,
gvc_message_queue->q.dev_num,
gvc_message_queue->q.format,
gvc_message_queue->q.cmd,
gvc_message_queue->q.data_len
);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
// GVCに対してコマンド送信
return 0;
}
// --------------------------------
// GVCキュー処理:0x91:リモコンデータ送信要求
// --------------------------------
int gvc_q_job_irtx(void * q_po)
{
// ----------------
// ローカル変数定義
// ----------------
char logstr[BUFF_SIZE];
GVC_MESSAGE_QUEUE_t * gvc_message_queue; // GVC メッセージキュー用ポインタ(キューデータにかぶせる)
int tx_len = 0; // 送信できたデータの長さ
// キューポインタにGVC_MESSAGE_QUEUE_tをかぶせる
gvc_message_queue = (GVC_MESSAGE_QUEUE_t *)q_po;
// ----------------
// GVCに対してコマンド送信
// ----------------
// 送信バッファにキューメッセージ部分をコピー
tx_buffer[0] = gvc_message_queue->q.msg_type; // gvc_serial_message->msg_type
tx_buffer[1] = gvc_message_queue->q.dev_num; // gvc_serial_message->dev_num
tx_buffer[2] = gvc_message_queue->q.format; // gvc_serial_message->format
tx_buffer[3] = gvc_message_queue->q.cmd; // gvc_serial_message->cmd
*(int *)&(tx_buffer[4]) = gvc_message_queue->q.data_len; // gvc_serial_message->data_len
memcpy((void *)&(tx_buffer[6]), gvc_message_queue->q.data, GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len);
// CRCを計算して、メッセージの最後に設定
tx_buffer[ GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len ] = GetCRC8((void *)tx_buffer, GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len);
// ↑データを送信する側は、データのCRCを計算したあとで
// そのCRCをデータの最後に連結して相手に送ればいい
// シリアルポートへのライト(checksumまで送信するので長さは+1される)
tx_len = write(gvc_port, (void *)tx_buffer, GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len + 1);
// きちんと送信できていないなら
if (tx_len < 0)
{
// もし割り込みによる中断だったら
if (errno == EINTR)
{
// LOGメッセージ設定
sprintf(logstr, "WRITE is EINTR. tx_len=%d, errno=%d", tx_len, errno);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
// それ以外の場合には
else
{
// LOGメッセージ設定
sprintf(logstr, "WRITE is OTHER ERROR !? tx_len=%d, errno=%d", tx_len, errno);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
}
// 送信したデータ長が実際と合致しないなら
else if (tx_len != (GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len + 1))
{
// LOGメッセージ設定
sprintf(logstr, "WRITE is SHORT !? tx_len=%d, org_len=%d", tx_len, (GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len + 1));
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
// きちんと送信できたなら
else
{
// ログ出力用文字列を生成
sprintf(logstr, "QUEUE IR TX : qtype=%lu, gvc_num=%d, msg_type=0x%02x, dev_num=0x%02x, format=0x%02x, cmd/result=0x%02x, data_len=0x%02x",
gvc_message_queue->qtype,
gvc_message_queue->q.gvc_num,
gvc_message_queue->q.msg_type,
gvc_message_queue->q.dev_num,
gvc_message_queue->q.format,
gvc_message_queue->q.cmd,
gvc_message_queue->q.data_len
);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
return 0;
}
// --------------------------------
// GVCキュー処理:0x92:リモコンデータ受信要求
// --------------------------------
int gvc_q_job_irrx(void * q_po)
{
// ----------------
// ローカル変数定義
// ----------------
char logstr[BUFF_SIZE];
GVC_MESSAGE_QUEUE_t * gvc_message_queue; // GVC メッセージキュー用ポインタ(キューデータにかぶせる)
int tx_len = 0; // 送信できたデータの長さ
// キューポインタにGVC_MESSAGE_QUEUE_tをかぶせる
gvc_message_queue = (GVC_MESSAGE_QUEUE_t *)q_po;
// ----------------
// GVCに対してコマンド送信
// ----------------
// 送信バッファにキューメッセージ部分をコピー
tx_buffer[0] = gvc_message_queue->q.msg_type; // gvc_serial_message->msg_type
tx_buffer[1] = gvc_message_queue->q.dev_num; // gvc_serial_message->dev_num
tx_buffer[2] = gvc_message_queue->q.format; // gvc_serial_message->format
tx_buffer[3] = gvc_message_queue->q.cmd; // gvc_serial_message->cmd
*(int *)&(tx_buffer[4]) = gvc_message_queue->q.data_len; // gvc_serial_message->data_len
memcpy((void *)&(tx_buffer[6]), gvc_message_queue->q.data, GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len);
// CRCを計算して、メッセージの最後に設定
tx_buffer[ GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len ] = GetCRC8((void *)tx_buffer, GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len);
// ↑データを送信する側は、データのCRCを計算したあとで
// そのCRCをデータの最後に連結して相手に送ればいい
// シリアルポートへのライト(checksumまで送信するので長さは+1される)
tx_len = write(gvc_port, (void *)tx_buffer, GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len + 1);
// きちんと送信できていないなら
if (tx_len < 0)
{
// もし割り込みによる中断だったら
if (errno == EINTR)
{
// LOGメッセージ設定
sprintf(logstr, "WRITE is EINTR. tx_len=%d, errno=%d", tx_len, errno);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
// それ以外の場合には
else
{
// LOGメッセージ設定
sprintf(logstr, "WRITE is OTHER ERROR !? tx_len=%d, errno=%d", tx_len, errno);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
}
// 送信したデータ長が実際と合致しないなら
else if (tx_len != (GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len + 1))
{
// LOGメッセージ設定
sprintf(logstr, "WRITE is SHORT !? tx_len=%d, org_len=%d", tx_len, (GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len + 1));
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
// きちんと送信できたなら
else
{
// ログ出力用文字列を生成
sprintf(logstr, "QUEUE IR RX : qtype=%lu, gvc_num=%d, msg_type=0x%02x, dev_num=0x%02x, format=0x%02x, cmd/result=0x%02x, data_len=0x%02x",
gvc_message_queue->qtype,
gvc_message_queue->q.gvc_num,
gvc_message_queue->q.msg_type,
gvc_message_queue->q.dev_num,
gvc_message_queue->q.format,
gvc_message_queue->q.cmd,
gvc_message_queue->q.data_len
);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
return 0;
}
// --------------------------------
// GVCキュー処理:0x93:リモコンデータ設定要求
// --------------------------------
int gvc_q_job_irset(void * q_po)
{
// ----------------
// ローカル変数定義
// ----------------
char logstr[BUFF_SIZE];
GVC_MESSAGE_QUEUE_t * gvc_message_queue; // GVC メッセージキュー用ポインタ(キューデータにかぶせる)
int hex_count;
int tx_len = 0; // 送信できたデータの長さ
// キューポインタにGVC_MESSAGE_QUEUE_tをかぶせる
gvc_message_queue = (GVC_MESSAGE_QUEUE_t *)q_po;
// ----------------
// GVCに対してコマンド送信
// ----------------
// 送信バッファにキューメッセージ部分をコピー
tx_buffer[0] = gvc_message_queue->q.msg_type; // gvc_serial_message->msg_type
tx_buffer[1] = gvc_message_queue->q.dev_num; // gvc_serial_message->dev_num
tx_buffer[2] = gvc_message_queue->q.format; // gvc_serial_message->format
tx_buffer[3] = gvc_message_queue->q.cmd; // gvc_serial_message->cmd
*(int *)&(tx_buffer[4]) = gvc_message_queue->q.data_len; // gvc_serial_message->data_len
memcpy((void *)&(tx_buffer[6]), gvc_message_queue->q.data, GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len);
// CRCを計算して、メッセージの最後に設定
tx_buffer[ GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len ] = GetCRC8((void *)tx_buffer, GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len);
// ↑データを送信する側は、データのCRCを計算したあとで
// そのCRCをデータの最後に連結して相手に送ればいい
// シリアルポートへのライト(checksumまで送信するので長さは+1される)
tx_len = write(gvc_port, (void *)tx_buffer, GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len + 1);
// きちんと送信できていないなら
if (tx_len < 0)
{
// もし割り込みによる中断だったら
if (errno == EINTR)
{
// LOGメッセージ設定
sprintf(logstr, "WRITE is EINTR. tx_len=%d, errno=%d", tx_len, errno);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
// それ以外の場合には
else
{
// LOGメッセージ設定
sprintf(logstr, "WRITE is OTHER ERROR !? tx_len=%d, errno=%d", tx_len, errno);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
}
// 送信したデータ長が実際と合致しないなら
else if (tx_len != (GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len + 1))
{
// LOGメッセージ設定
sprintf(logstr, "WRITE is SHORT !? tx_len=%d, org_len=%d", tx_len, (GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len + 1));
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
// きちんと送信できたなら
else
{
// ログ出力用文字列を生成
sprintf(logstr, "QUEUE IR SET : qtype=%lu, gvc_num=%d, msg_type=0x%02x, dev_num=0x%02x, format=0x%02x, cmd/result=0x%02x, data_len=%0d, data=",
gvc_message_queue->qtype,
gvc_message_queue->q.gvc_num,
gvc_message_queue->q.msg_type,
gvc_message_queue->q.dev_num,
gvc_message_queue->q.format,
gvc_message_queue->q.cmd,
gvc_message_queue->q.data_len
);
// QUEUE~data=までの文字列の長さを取得
tx_len = strlen(logstr);
// data=の後ろに16進でデータを書いていく
for (hex_count = 0; hex_count < gvc_message_queue->q.data_len; hex_count++)
{
sprintf((char *)logstr + tx_len, "%02X", (int)gvc_message_queue->q.data[hex_count]);
tx_len += 2;
}
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
return 0;
}
// --------------------------------
// GVCキュー処理:0x94:リモコンデータ取得要求
// --------------------------------
int gvc_q_job_irget(void * q_po)
{
// ----------------
// ローカル変数定義
// ----------------
char logstr[BUFF_SIZE];
GVC_MESSAGE_QUEUE_t * gvc_message_queue; // GVC メッセージキュー用ポインタ(キューデータにかぶせる)
int tx_len = 0; // 送信できたデータの長さ
// キューポインタにGVC_MESSAGE_QUEUE_tをかぶせる
gvc_message_queue = (GVC_MESSAGE_QUEUE_t *)q_po;
// データ長がある場合、リモコンデータを保存するファイルを指定されている可能性があるので、まず開いてみる
if (gvc_message_queue->q.data_len > 0 && gvc_message_queue->q.data_len == strlen((char *)gvc_message_queue->q.data))
{
// そのファイルが開けるか試してみる
datafp = fopen((char *)gvc_message_queue->q.data, "wb");
// ファイルが開けなかったら
if (datafp == NULL)
{
// データ格納フラグ初期化
datafp_flag = 0;
// データ格納フラグは変化なし
// LOGメッセージ設定
sprintf(logstr, "CANNOT OPEN IR DATA FILE: %s", gvc_message_queue->q.data);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
else
{
// データ格納フラグを待ち状態に
datafp_flag = 1;
// LOGメッセージ設定
sprintf(logstr, "OPEN IR DATA FILE: %s", gvc_message_queue->q.data);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
// データ長リセット、GVCに対してファイル名を送っても意味が無いので。
// このif{}の外でリセットしないのは、メッセージそのものがおかしかったときに気がつかないと困るから
gvc_message_queue->q.data_len = 0;
}
// ----------------
// GVCに対してコマンド送信
// ----------------
// 送信バッファにキューメッセージ部分をコピー
tx_buffer[0] = gvc_message_queue->q.msg_type; // gvc_serial_message->msg_type
tx_buffer[1] = gvc_message_queue->q.dev_num; // gvc_serial_message->dev_num
tx_buffer[2] = gvc_message_queue->q.format; // gvc_serial_message->format
tx_buffer[3] = gvc_message_queue->q.cmd; // gvc_serial_message->cmd
*(int *)&(tx_buffer[4]) = gvc_message_queue->q.data_len; // gvc_serial_message->data_len
memcpy((void *)&(tx_buffer[6]), gvc_message_queue->q.data, GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len);
// CRCを計算して、メッセージの最後に設定
tx_buffer[ GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len ] = GetCRC8((void *)tx_buffer, GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len);
// ↑データを送信する側は、データのCRCを計算したあとで
// そのCRCをデータの最後に連結して相手に送ればいい
// シリアルポートへのライト(checksumまで送信するので長さは+1される)
tx_len = write(gvc_port, (void *)tx_buffer, GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len + 1);
// きちんと送信できていないなら
if (tx_len < 0)
{
// もし割り込みによる中断だったら
if (errno == EINTR)
{
// LOGメッセージ設定
sprintf(logstr, "WRITE is EINTR. tx_len=%d, errno=%d", tx_len, errno);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
// それ以外の場合には
else
{
// LOGメッセージ設定
sprintf(logstr, "WRITE is OTHER ERROR !? tx_len=%d, errno=%d", tx_len, errno);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
}
// 送信したデータ長が実際と合致しないなら
else if (tx_len != (GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len + 1))
{
// LOGメッセージ設定
sprintf(logstr, "WRITE is SHORT !? tx_len=%d, org_len=%d", tx_len, (GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len + 1));
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
// きちんと送信できたなら
else
{
// ログ出力用文字列を生成
sprintf(logstr, "QUEUE IR GET : qtype=%lu, gvc_num=%d, msg_type=0x%02x, dev_num=0x%02x, format=0x%02x, cmd/result=0x%02x, data_len=0x%02x",
gvc_message_queue->qtype,
gvc_message_queue->q.gvc_num,
gvc_message_queue->q.msg_type,
gvc_message_queue->q.dev_num,
gvc_message_queue->q.format,
gvc_message_queue->q.cmd,
gvc_message_queue->q.data_len
);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
return 0;
}
// --------------------------------
// GVCキュー処理:0x95:リモコンデータ削除要求
// --------------------------------
int gvc_q_job_irdel(void * q_po)
{
// ----------------
// ローカル変数定義
// ----------------
char logstr[BUFF_SIZE];
GVC_MESSAGE_QUEUE_t * gvc_message_queue; // GVC メッセージキュー用ポインタ(キューデータにかぶせる)
int tx_len = 0; // 送信できたデータの長さ
// キューポインタにGVC_MESSAGE_QUEUE_tをかぶせる
gvc_message_queue = (GVC_MESSAGE_QUEUE_t *)q_po;
// ----------------
// GVCに対してコマンド送信
// ----------------
// 送信バッファにキューメッセージ部分をコピー
tx_buffer[0] = gvc_message_queue->q.msg_type; // gvc_serial_message->msg_type
tx_buffer[1] = gvc_message_queue->q.dev_num; // gvc_serial_message->dev_num
tx_buffer[2] = gvc_message_queue->q.format; // gvc_serial_message->format
tx_buffer[3] = gvc_message_queue->q.cmd; // gvc_serial_message->cmd
*(int *)&(tx_buffer[4]) = gvc_message_queue->q.data_len; // gvc_serial_message->data_len
memcpy((void *)&(tx_buffer[6]), gvc_message_queue->q.data, GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len);
// CRCを計算して、メッセージの最後に設定
tx_buffer[ GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len ] = GetCRC8((void *)tx_buffer, GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len);
// ↑データを送信する側は、データのCRCを計算したあとで
// そのCRCをデータの最後に連結して相手に送ればいい
// シリアルポートへのライト(checksumまで送信するので長さは+1される)
tx_len = write(gvc_port, (void *)tx_buffer, GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len + 1);
// きちんと送信できていないなら
if (tx_len < 0)
{
// もし割り込みによる中断だったら
if (errno == EINTR)
{
// LOGメッセージ設定
sprintf(logstr, "WRITE is EINTR. tx_len=%d, errno=%d", tx_len, errno);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
// それ以外の場合には
else
{
// LOGメッセージ設定
sprintf(logstr, "WRITE is OTHER ERROR !? tx_len=%d, errno=%d", tx_len, errno);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
}
// 送信したデータ長が実際と合致しないなら
else if (tx_len != (GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len + 1))
{
// LOGメッセージ設定
sprintf(logstr, "WRITE is SHORT !? tx_len=%d, org_len=%d", tx_len, (GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len + 1));
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
// きちんと送信できたなら
else
{
// ログ出力用文字列を生成
sprintf(logstr, "QUEUE IR DEL : qtype=%lu, gvc_num=%d, msg_type=0x%02x, dev_num=0x%02x, format=0x%02x, cmd/result=0x%02x, data_len=0x%02x",
gvc_message_queue->qtype,
gvc_message_queue->q.gvc_num,
gvc_message_queue->q.msg_type,
gvc_message_queue->q.dev_num,
gvc_message_queue->q.format,
gvc_message_queue->q.cmd,
gvc_message_queue->q.data_len
);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
return 0;
}
// --------------------------------
// GVCキュー処理:0x7e:マスターコントローラーリセット要求
// --------------------------------
int gvc_q_job_masterreset(void * q_po)
{
// ----------------
// ローカル変数定義
// ----------------
char logstr[BUFF_SIZE];
GVC_MESSAGE_QUEUE_t * gvc_message_queue; // GVC メッセージキュー用ポインタ(キューデータにかぶせる)
int tx_len = 0; // 送信できたデータの長さ
// キューポインタにGVC_MESSAGE_QUEUE_tをかぶせる
gvc_message_queue = (GVC_MESSAGE_QUEUE_t *)q_po;
// ----------------
// GVCに対してコマンド送信
// ----------------
// 送信バッファにキューメッセージ部分をコピー
tx_buffer[0] = gvc_message_queue->q.msg_type; // gvc_serial_message->msg_type
tx_buffer[1] = gvc_message_queue->q.dev_num; // gvc_serial_message->dev_num
tx_buffer[2] = gvc_message_queue->q.format; // gvc_serial_message->format
tx_buffer[3] = gvc_message_queue->q.cmd; // gvc_serial_message->cmd
*(int *)&(tx_buffer[4]) = gvc_message_queue->q.data_len; // gvc_serial_message->data_len
memcpy((void *)&(tx_buffer[6]), gvc_message_queue->q.data, GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len);
// CRCを計算して、メッセージの最後に設定
tx_buffer[ GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len ] = GetCRC8((void *)tx_buffer, GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len);
// ↑データを送信する側は、データのCRCを計算したあとで
// そのCRCをデータの最後に連結して相手に送ればいい
// シリアルポートへのライト(checksumまで送信するので長さは+1される)
tx_len = write(gvc_port, (void *)tx_buffer, GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len + 1);
// きちんと送信できていないなら
if (tx_len < 0)
{
// もし割り込みによる中断だったら
if (errno == EINTR)
{
// LOGメッセージ設定
sprintf(logstr, "WRITE is EINTR. tx_len=%d, errno=%d", tx_len, errno);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
// それ以外の場合には
else
{
// LOGメッセージ設定
sprintf(logstr, "WRITE is OTHER ERROR !? tx_len=%d, errno=%d", tx_len, errno);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
}
// 送信したデータ長が実際と合致しないなら
else if (tx_len != (GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len + 1))
{
// LOGメッセージ設定
sprintf(logstr, "WRITE is SHORT !? tx_len=%d, org_len=%d", tx_len, (GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len + 1));
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
// きちんと送信できたなら
else
{
// ログ出力用文字列を生成
sprintf(logstr, "QUEUE MASTER RESET : qtype=%lu, gvc_num=%d, msg_type=0x%02x, dev_num=0x%02x, format=0x%02x, cmd/result=0x%02x, data_len=0x%02x",
gvc_message_queue->qtype,
gvc_message_queue->q.gvc_num,
gvc_message_queue->q.msg_type,
gvc_message_queue->q.dev_num,
gvc_message_queue->q.format,
gvc_message_queue->q.cmd,
gvc_message_queue->q.data_len
);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
return 0;
}
// --------------------------------
// GVCキュー処理:0x7e:マスターコントローラーリスタート要求
// --------------------------------
int gvc_q_job_masterrestart(void * q_po)
{
// ----------------
// ローカル変数定義
// ----------------
char logstr[BUFF_SIZE];
GVC_MESSAGE_QUEUE_t * gvc_message_queue; // GVC メッセージキュー用ポインタ(キューデータにかぶせる)
int tx_len = 0; // 送信できたデータの長さ
// キューポインタにGVC_MESSAGE_QUEUE_tをかぶせる
gvc_message_queue = (GVC_MESSAGE_QUEUE_t *)q_po;
// ----------------
// GVCに対してコマンド送信
// ----------------
// 送信バッファにキューメッセージ部分をコピー
tx_buffer[0] = gvc_message_queue->q.msg_type; // gvc_serial_message->msg_type
tx_buffer[1] = gvc_message_queue->q.dev_num; // gvc_serial_message->dev_num
tx_buffer[2] = gvc_message_queue->q.format; // gvc_serial_message->format
tx_buffer[3] = gvc_message_queue->q.cmd; // gvc_serial_message->cmd
*(int *)&(tx_buffer[4]) = gvc_message_queue->q.data_len; // gvc_serial_message->data_len
memcpy((void *)&(tx_buffer[6]), gvc_message_queue->q.data, GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len);
// CRCを計算して、メッセージの最後に設定
tx_buffer[ GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len ] = GetCRC8((void *)tx_buffer, GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len);
// ↑データを送信する側は、データのCRCを計算したあとで
// そのCRCをデータの最後に連結して相手に送ればいい
// シリアルポートへのライト(checksumまで送信するので長さは+1される)
tx_len = write(gvc_port, (void *)tx_buffer, GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len + 1);
// きちんと送信できていないなら
if (tx_len < 0)
{
// もし割り込みによる中断だったら
if (errno == EINTR)
{
// LOGメッセージ設定
sprintf(logstr, "WRITE is EINTR. tx_len=%d, errno=%d", tx_len, errno);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
// それ以外の場合には
else
{
// LOGメッセージ設定
sprintf(logstr, "WRITE is OTHER ERROR !? tx_len=%d, errno=%d", tx_len, errno);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
}
// 送信したデータ長が実際と合致しないなら
else if (tx_len != (GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len + 1))
{
// LOGメッセージ設定
sprintf(logstr, "WRITE is SHORT !? tx_len=%d, org_len=%d", tx_len, (GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len + 1));
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
// きちんと送信できたなら
else
{
// ログ出力用文字列を生成
sprintf(logstr, "QUEUE MASTER RESTART : qtype=%lu, gvc_num=%d, msg_type=0x%02x, dev_num=0x%02x, format=0x%02x, cmd/result=0x%02x, data_len=0x%02x",
gvc_message_queue->qtype,
gvc_message_queue->q.gvc_num,
gvc_message_queue->q.msg_type,
gvc_message_queue->q.dev_num,
gvc_message_queue->q.format,
gvc_message_queue->q.cmd,
gvc_message_queue->q.data_len
);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
return 0;
}
// --------------------------------
// GVCキュー処理:0x7f:マスターコントローラーストップ要求
// --------------------------------
int gvc_q_job_masterstop(void * q_po)
{
// ----------------
// ローカル変数定義
// ----------------
char logstr[BUFF_SIZE];
GVC_MESSAGE_QUEUE_t * gvc_message_queue; // GVC メッセージキュー用ポインタ(キューデータにかぶせる)
int tx_len = 0; // 送信できたデータの長さ
// キューポインタにGVC_MESSAGE_QUEUE_tをかぶせる
gvc_message_queue = (GVC_MESSAGE_QUEUE_t *)q_po;
// ----------------
// GVCに対してコマンド送信
// ----------------
// 送信バッファにキューメッセージ部分をコピー
tx_buffer[0] = gvc_message_queue->q.msg_type; // gvc_serial_message->msg_type
tx_buffer[1] = gvc_message_queue->q.dev_num; // gvc_serial_message->dev_num
tx_buffer[2] = gvc_message_queue->q.format; // gvc_serial_message->format
tx_buffer[3] = gvc_message_queue->q.cmd; // gvc_serial_message->cmd
*(int *)&(tx_buffer[4]) = gvc_message_queue->q.data_len; // gvc_serial_message->data_len
memcpy((void *)&(tx_buffer[6]), gvc_message_queue->q.data, GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len);
// CRCを計算して、メッセージの最後に設定
tx_buffer[ GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len ] = GetCRC8((void *)tx_buffer, GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len);
// ↑データを送信する側は、データのCRCを計算したあとで
// そのCRCをデータの最後に連結して相手に送ればいい
// シリアルポートへのライト(checksumまで送信するので長さは+1される)
tx_len = write(gvc_port, (void *)tx_buffer, GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len + 1);
// きちんと送信できていないなら
if (tx_len < 0)
{
// もし割り込みによる中断だったら
if (errno == EINTR)
{
// LOGメッセージ設定
sprintf(logstr, "WRITE is EINTR. tx_len=%d, errno=%d", tx_len, errno);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
// それ以外の場合には
else
{
// LOGメッセージ設定
sprintf(logstr, "WRITE is OTHER ERROR !? tx_len=%d, errno=%d", tx_len, errno);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
}
// 送信したデータ長が実際と合致しないなら
else if (tx_len != (GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len + 1))
{
// LOGメッセージ設定
sprintf(logstr, "WRITE is SHORT !? tx_len=%d, org_len=%d", tx_len, (GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_message_queue->q.data_len + 1));
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
// きちんと送信できたなら
else
{
// ログ出力用文字列を生成
sprintf(logstr, "QUEUE MASTER STOP : qtype=%lu, gvc_num=%d, msg_type=0x%02x, dev_num=0x%02x, format=0x%02x, cmd/result=0x%02x, data_len=0x%02x",
gvc_message_queue->qtype,
gvc_message_queue->q.gvc_num,
gvc_message_queue->q.msg_type,
gvc_message_queue->q.dev_num,
gvc_message_queue->q.format,
gvc_message_queue->q.cmd,
gvc_message_queue->q.data_len
);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
return 0;
}
// --------------------------------
// GVCキュー処理:0xff:gvcdストップ要求
// --------------------------------
int gvc_q_job_daemonstop(void * q_po)
{
// ----------------
// ローカル変数定義
// ----------------
char logstr[BUFF_SIZE];
GVC_MESSAGE_QUEUE_t * gvc_message_queue; // GVC メッセージキュー用ポインタ(キューデータにかぶせる)
// キューポインタにGVC_MESSAGE_QUEUE_tをかぶせる
gvc_message_queue = (GVC_MESSAGE_QUEUE_t *)q_po;
// ログ出力用文字列を生成
sprintf(logstr, "QUEUE DAEMON STOP : qtype=%lu, gvc_num=%d, msg_type=0x%02x, dev_num=0x%02x, format=0x%02x, cmd/result=0x%02x, data_len=0x%02x",
gvc_message_queue->qtype,
gvc_message_queue->q.gvc_num,
gvc_message_queue->q.msg_type,
gvc_message_queue->q.dev_num,
gvc_message_queue->q.format,
gvc_message_queue->q.cmd,
gvc_message_queue->q.data_len
);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
// GVCに対してコマンド送信
return 0;
}
// ------------------------------------------
// Sub Routine/GVCメッセージ処理
// ------------------------------------------
// --------------------------------
// GVCメッセージ処理:ダミー
// --------------------------------
int gvc_msg_job_dummy(void * msg_po)
{
// ----------------
// ローカル変数定義
// ----------------
char logstr[BUFF_SIZE];
GVC_SERIAL_MESSAGE_t * gvc_serial_message; // GVC シリアルメッセージ用ポインタ(シリアルデータにかぶせる)
// メッセージポインタにGVC_SERIAL_MESSAGE_tをかぶせる
gvc_serial_message = (GVC_SERIAL_MESSAGE_t *)msg_po;
// ログ出力用文字列を生成
sprintf(logstr, "MSG DUMMY : msg_type=0x%02x, dev_num=0x%02x, format=0x%02x, cmd/result=0x%02x, data_len=0x%02x",
gvc_serial_message->msg_type,
gvc_serial_message->dev_num,
gvc_serial_message->format,
gvc_serial_message->cmd,
gvc_serial_message->data_len
);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
return 0;
}
// --------------------------------
// GVCメッセージ処理:デリミタメッセージ
// --------------------------------
int gvc_msg_job_delimiterframe(void * msg_po)
{
// ----------------
// ローカル変数定義
// ----------------
char logstr[BUFF_SIZE];
GVC_SERIAL_MESSAGE_t * gvc_serial_message; // GVC シリアルメッセージ用ポインタ(シリアルデータにかぶせる)
// メッセージポインタにGVC_SERIAL_MESSAGE_tをかぶせる
gvc_serial_message = (GVC_SERIAL_MESSAGE_t *)msg_po;
// ログ出力用文字列を生成
sprintf(logstr, "MSG DELIMITER : msg_type=0x%02x, dev_num=0x%02x, format=0x%02x, cmd/result=0x%02x, data_len=0x%02x",
gvc_serial_message->msg_type,
gvc_serial_message->dev_num,
gvc_serial_message->format,
gvc_serial_message->cmd,
gvc_serial_message->data_len
);
// 普段はうざいので動かさない
// ログにメッセージを出力
// put_log(gvcd_mode, logstr);
// GVCコマンド送信可能状態を送信可能(=1)に設定
gvc_cmd_ready = 1;
return 0;
}
// --------------------------------
// GVCメッセージ処理:その他のメッセージ
// --------------------------------
int gvc_msg_job_other(void * msg_po)
{
// ----------------
// ローカル変数定義
// ----------------
char logstr[BUFF_SIZE];
int loglen;
GVC_SERIAL_MESSAGE_t * gvc_serial_message; // GVC シリアルメッセージ用ポインタ(シリアルデータにかぶせる)
// メッセージポインタにGVC_SERIAL_MESSAGE_tをかぶせる
gvc_serial_message = (GVC_SERIAL_MESSAGE_t *)msg_po;
// データがバイナリの場合(formatなどで判別すること)には、HEX表示にしたり「.」表示にしたりなど工夫すること!!
// データがあるなら
if (gvc_serial_message->data_len > 0)
{
// ログ出力用文字列を生成
sprintf(logstr, "MSG OTHER : msg_type=0x%02x, dev_num=0x%02x, format=0x%02x, cmd/result=0x%02x, data_len=%0d, data=",
gvc_serial_message->msg_type,
gvc_serial_message->dev_num,
gvc_serial_message->format,
gvc_serial_message->cmd,
gvc_serial_message->data_len);
loglen = strlen(logstr);
memcpy(logstr + loglen, gvc_serial_message->data, gvc_serial_message->data_len);
logstr[loglen + gvc_serial_message->data_len] = 0x00;
}
// データがないなら
else
{
// ログ出力用文字列を生成
sprintf(logstr, "MSG OTHER : msg_type=0x%02x, dev_num=0x%02x, format=0x%02x, cmd/result=0x%02x, data_len=%0d",
gvc_serial_message->msg_type,
gvc_serial_message->dev_num,
gvc_serial_message->format,
gvc_serial_message->cmd,
gvc_serial_message->data_len
);
}
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
return 0;
}
// --------------------------------
// GVCメッセージ処理:距離
// --------------------------------
int gvc_msg_job_distance(void * msg_po)
{
// ----------------
// ローカル変数定義
// ----------------
char logstr[BUFF_SIZE];
int loglen;
GVC_SERIAL_MESSAGE_t * gvc_serial_message; // GVC シリアルメッセージ用ポインタ(シリアルデータにかぶせる)
// メッセージポインタにGVC_SERIAL_MESSAGE_tをかぶせる
gvc_serial_message = (GVC_SERIAL_MESSAGE_t *)msg_po;
// データがバイナリの場合(formatなどで判別すること)には、HEX表示にしたり「.」表示にしたりなど工夫すること!!
// ログ出力用文字列を生成
sprintf(logstr, "MSG DIST : msg_type=0x%02x, dev_num=0x%02x, format=0x%02x, cmd/result=0x%02x, data_len=%0d, data=",
gvc_serial_message->msg_type,
gvc_serial_message->dev_num,
gvc_serial_message->format,
gvc_serial_message->cmd,
gvc_serial_message->data_len);
loglen = strlen(logstr);
memcpy(logstr + loglen, gvc_serial_message->data, gvc_serial_message->data_len);
logstr[loglen + gvc_serial_message->data_len] = 0x00;
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
return 0;
}
// --------------------------------
// GVCメッセージ処理:湿度
// --------------------------------
int gvc_msg_job_humidity(void * msg_po)
{
// ----------------
// ローカル変数定義
// ----------------
char logstr[BUFF_SIZE];
int loglen;
GVC_SERIAL_MESSAGE_t * gvc_serial_message; // GVC シリアルメッセージ用ポインタ(シリアルデータにかぶせる)
// メッセージポインタにGVC_SERIAL_MESSAGE_tをかぶせる
gvc_serial_message = (GVC_SERIAL_MESSAGE_t *)msg_po;
// データがバイナリの場合(formatなどで判別すること)には、HEX表示にしたり「.」表示にしたりなど工夫すること!!
// ログ出力用文字列を生成
sprintf(logstr, "MSG HUMI : msg_type=0x%02x, dev_num=0x%02x, format=0x%02x, cmd/result=0x%02x, data_len=%0d, data=",
gvc_serial_message->msg_type,
gvc_serial_message->dev_num,
gvc_serial_message->format,
gvc_serial_message->cmd,
gvc_serial_message->data_len);
loglen = strlen(logstr);
memcpy(logstr + loglen, gvc_serial_message->data, gvc_serial_message->data_len);
logstr[loglen + gvc_serial_message->data_len] = 0x00;
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
return 0;
}
// --------------------------------
// GVCメッセージ処理:赤外線
// --------------------------------
int gvc_msg_job_ir(void * msg_po)
{
// ----------------
// ローカル変数定義
// ----------------
char logstr[BUFF_SIZE];
int loglen;
int hex_count;
GVC_SERIAL_MESSAGE_t * gvc_serial_message; // GVC シリアルメッセージ用ポインタ(シリアルデータにかぶせる)
// メッセージポインタにGVC_SERIAL_MESSAGE_tをかぶせる
gvc_serial_message = (GVC_SERIAL_MESSAGE_t *)msg_po;
// ログ出力用文字列を生成
sprintf(logstr, "MSG IR : msg_type=0x%02x, dev_num=0x%02x, format=0x%02x, cmd/result=0x%02x, data_len=%0d, data=",
gvc_serial_message->msg_type,
gvc_serial_message->dev_num,
gvc_serial_message->format,
gvc_serial_message->cmd,
gvc_serial_message->data_len);
loglen = strlen(logstr);
// もしフォーマットがバイナリなら
if (gvc_serial_message->format == 0x31)
{
// 当面はASCIIに変換してテキスト出力…TBD
for (hex_count = 0; hex_count < gvc_serial_message->data_len; hex_count++)
{
sprintf((char *)logstr + loglen, "%02X", (int)gvc_serial_message->data[hex_count]);
loglen += 2;
}
}
// そうではないなら
else
{
// 当面はそのままテキスト出力…TBD
memcpy(logstr + loglen, gvc_serial_message->data, gvc_serial_message->data_len);
logstr[loglen + gvc_serial_message->data_len] = 0x00;
}
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
// もしデータ格納フラグが待ち状態(=1)で、かつデータファイルがオープンされているなら
if (datafp_flag == 1 && datafp != NULL)
{
// データファイルにデータを出力
fwrite(gvc_serial_message->data, sizeof(char), gvc_serial_message->data_len, datafp);
// データファイルを閉じる
fclose(datafp);
// データ格納フラグ初期化
datafp_flag = 0;
}
// 出力されたデータを確認するには「od -tx1z 出力ファイル名」のようにするといいよ
return 0;
}
// --------------------------------
// GVCメッセージ処理:照度
// --------------------------------
int gvc_msg_job_light(void * msg_po)
{
// ----------------
// ローカル変数定義
// ----------------
char logstr[BUFF_SIZE];
int loglen;
GVC_SERIAL_MESSAGE_t * gvc_serial_message; // GVC シリアルメッセージ用ポインタ(シリアルデータにかぶせる)
// メッセージポインタにGVC_SERIAL_MESSAGE_tをかぶせる
gvc_serial_message = (GVC_SERIAL_MESSAGE_t *)msg_po;
// データがバイナリの場合(formatなどで判別すること)には、HEX表示にしたり「.」表示にしたりなど工夫すること!!
// ログ出力用文字列を生成
sprintf(logstr, "MSG LIGHT : msg_type=0x%02x, dev_num=0x%02x, format=0x%02x, cmd/result=0x%02x, data_len=%0d, data=",
gvc_serial_message->msg_type,
gvc_serial_message->dev_num,
gvc_serial_message->format,
gvc_serial_message->cmd,
gvc_serial_message->data_len);
loglen = strlen(logstr);
memcpy(logstr + loglen, gvc_serial_message->data, gvc_serial_message->data_len);
logstr[loglen + gvc_serial_message->data_len] = 0x00;
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
return 0;
}
// --------------------------------
// GVCメッセージ処理:大気圧、圧力
// --------------------------------
int gvc_msg_job_pressure(void * msg_po)
{
// ----------------
// ローカル変数定義
// ----------------
char logstr[BUFF_SIZE];
int loglen;
GVC_SERIAL_MESSAGE_t * gvc_serial_message; // GVC シリアルメッセージ用ポインタ(シリアルデータにかぶせる)
// メッセージポインタにGVC_SERIAL_MESSAGE_tをかぶせる
gvc_serial_message = (GVC_SERIAL_MESSAGE_t *)msg_po;
// データがバイナリの場合(formatなどで判別すること)には、HEX表示にしたり「.」表示にしたりなど工夫すること!!
// ログ出力用文字列を生成
sprintf(logstr, "MSG PRES : msg_type=0x%02x, dev_num=0x%02x, format=0x%02x, cmd/result=0x%02x, data_len=%0d, data=",
gvc_serial_message->msg_type,
gvc_serial_message->dev_num,
gvc_serial_message->format,
gvc_serial_message->cmd,
gvc_serial_message->data_len);
loglen = strlen(logstr);
memcpy(logstr + loglen, gvc_serial_message->data, gvc_serial_message->data_len);
logstr[loglen + gvc_serial_message->data_len] = 0x00;
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
return 0;
}
// --------------------------------
// GVCメッセージ処理:温度
// --------------------------------
int gvc_msg_job_temperature(void * msg_po)
{
// ----------------
// ローカル変数定義
// ----------------
char logstr[BUFF_SIZE];
int loglen;
GVC_SERIAL_MESSAGE_t * gvc_serial_message; // GVC シリアルメッセージ用ポインタ(シリアルデータにかぶせる)
// メッセージポインタにGVC_SERIAL_MESSAGE_tをかぶせる
gvc_serial_message = (GVC_SERIAL_MESSAGE_t *)msg_po;
// データがバイナリの場合(formatなどで判別すること)には、HEX表示にしたり「.」表示にしたりなど工夫すること!!
// ログ出力用文字列を生成
sprintf(logstr, "MSG TEMP : msg_type=0x%02x, dev_num=0x%02x, format=0x%02x, cmd/result=0x%02x, data_len=%0d, data=",
gvc_serial_message->msg_type,
gvc_serial_message->dev_num,
gvc_serial_message->format,
gvc_serial_message->cmd,
gvc_serial_message->data_len);
loglen = strlen(logstr);
memcpy(logstr + loglen, gvc_serial_message->data, gvc_serial_message->data_len);
logstr[loglen + gvc_serial_message->data_len] = 0x00;
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
return 0;
}
// ------------------------------------------
// Sub Routine/その他
// ------------------------------------------
// --------------------------------
// シリアルポートの初期化
// --------------------------------
void serial_reset(int fd)
{
// http://linuxjm.sourceforge.jp/html/LDP_man-pages/man3/termios.3.html
// 標準ではカノニカルモードで、デリミタもあらかじめ設定されている
// ThinkPadに入れたLinuxとかではなんら問題が無かったが、なぜかRaspberry Piではシリアルポートがうまく
// 使えず困っていた。Pidora(Fedora Remix)にlogserialというのがあったのでソースを見てみたところ、
// どうも文字サイズの初期化で「(tio.c_cflag & ~CSIZE)」をORとった上でCS8としないとだめみたいで、
// ちなみに他のパラメータはどであっても関係なかった
// ----------------
// ローカル変数定義
// ----------------
// termioテーブルローカル宣言
struct termios tio;
// ローカル変数を0で初期化
memset(&tio, 0, sizeof(tio));
// 現在の設定値を取得
tcgetattr(fd, &tio);
// 入力ボーレートを設定
cfsetispeed(&tio, BAUD_RATE);
// 出力ボーレートを設定
cfsetospeed(&tio, BAUD_RATE);
// 文字サイズとして8ビットを設定
tio.c_cflag = (tio.c_cflag & ~CSIZE) | CS8;
// モデムの制御線を無視、受信有効、フレームエラーおよびパリティエラーを無視
tio.c_cflag |= (CLOCAL | CREAD | IGNPAR );
// ノンパリティ(偶数奇数パリティも外す=この状態だと奇数パリティ)
tio.c_cflag &= ~(PARENB | PARODD);
// 入力モードの設定
// 入力中の BREAK 信号を無視
tio.c_iflag = IGNBRK;
// 出力の XON/XOFF フロー制御を無効、入力の XON/XOFF フロー制御を無効、任意の文字を入力すると、停止していた出力を再開したりする機能も無効
tio.c_iflag &= ~(IXON|IXOFF|IXANY);
// 出力モードは0クリア
tio.c_oflag = 0;
// ローカルモードも0クリア(非カノニカルモードになる)
tio.c_lflag = 0;
/// 非カノニカルモードの場合の最小受信文字数
tio.c_cc[VMIN] = 1;
/// 非カノニカルモードの場合のタイムアウト時間
tio.c_cc[VTIME] = 5;
// 端末に関連したパラメータを設定(TCSANOW:すぐに反映)
tcsetattr(fd, TCSANOW, &tio);
// 戻る
}
// --------------------------------
// 現在時間を文字列で得る
// --------------------------------
void get_daytime(char *daytime_str)
{
// ----------------
// ローカル変数定義
// ----------------
// 日時情報テーブルローカル宣言
struct timeval tv;
// タイムゾーンテーブルローカル宣言(実際には使われない)
struct timezone tz;
// 文字列日時情報テーブルローカル宣言
struct tm now;
// ローカル変数を0で初期化
memset(&tv, 0, sizeof(tv));
memset(&tz, 0, sizeof(tz));
// 日時情報文字列を初期化
memset(daytime_str, 0, DAYTIME_LEN);
// 現在日時を取得
gettimeofday(&tv, &tz);
// 文字列日時情報に変換
localtime_r((const time_t*)&(tv.tv_sec), &now);
// 日時情報文字列を引数の文字列ポインタに設定
sprintf(daytime_str, "%04d/%02d/%02d %02d:%02d:%02d",
now.tm_year + 1900,
now.tm_mon + 1,
now.tm_mday,
now.tm_hour,
now.tm_min,
now.tm_sec );
// 戻る
}
// --------------------------------
// シグナルハンドラ(ALARM)
// --------------------------------
void signal_alarm()
{
// ----------------
// ローカル変数定義
// ----------------
char logstr[BUFF_SIZE];
// SYSLOGメッセージ設定
sprintf(logstr, "ALARM, Interrupt %s", SOFTNAME);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
// --------------------------------------------------
// シグナルハンドラ(SIGHUP)
// --------------------------------------------------
void signal_sighup()
{
// ----------------
// ローカル変数定義
// ----------------
char logstr[BUFF_SIZE];
// SYSLOGメッセージ設定
sprintf(logstr, "SIGHUP, Stopped %s", SOFTNAME);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
// 終わり
exit(EXIT_SUCCESS);
}
// --------------------------------
// ログ出力
// --------------------------------
void put_log(int mode, char *logstr)
{
// 通常モード(SYSLOG出力)なら
if (mode == 0)
{
// syslogにメッセージを出力
syslog(LOG_NOTICE, logstr);
}
// ログファイル別出力モードなら
else if (mode == 1)
{
// 別ファイルに出力
write(gvc_log_fp, (void *)logstr, strlen(logstr));
}
// 上記以外(ダンプモードとか)なら
else
{
// 現在日時と合わせてログ文字列を表示
printf("[%s] %s", daytime_str, logstr);
}
}
// --------------------------------------------------
// Main Routine
// --------------------------------------------------
int main(int argc, char *argv[])
{
// ----------------
// ローカル変数定義
// ----------------
FILE *pidfile; // PIDファイル用ポインタ
struct stat pidstat; // PIDファイル情報
int argnum; // 引数カウント用
int func_num; // キュー/メッセージ処理関数番号
// logserial
fd_set fds; // file descriptor set for reading
struct timeval tv; // struct for time interval for select
int rx_pos = 0; // 受信データの位置
int rx_len = 0; // 受信データの長さ
int rx_buffer_len = 0; // 受信バッファの長さ
int rx_remainder; // 受信バッファの残りの先頭位置
int rx_remainder_len = 0; // 受信バッファの残りの長さ
/// int tx_len = 0; // 送信できたデータの長さ
int check_char; // 受信バッファのチェック用ポインタ
GVC_SERIAL_MESSAGE_t * gvc_serial_message; // GVC シリアルメッセージ用ポインタ(シリアルデータにかぶせる)
GVC_MESSAGE_QUEUE_t rcv_message_queue; // 受信メッセージキュー
/// GVC_MESSAGE_QUEUE_t send_message_queue; // 送信メッセージキュー
int message_qid; // メッセージキューID
int msgq_length; // メッセージの長さ
key_t msgq_key; // メッセージキューのキー
int msgq_result; // メッセージキュー送受信結果
char logstr[BUFF_SIZE];
// ----------------
// 引数確認
// ----------------
// 引数が2より少ないなら
if (argc < 2)
{
// ソフト名と使い方を表示
printf("%s %s\n\n", SOFTNAME, VERSION);
printf("%s [end]\n\n", argv[0]);
printf(" -> %s /dev/ttyUSB0 [log=file]\n", argv[0]);
// 終わり
exit(1);
}
// 引数を検査
for (argnum = 1; argnum < argc; argnum++)
{
// 引数の中にログファイル別出力指定があるなら
if (strcasecmp("log=file", argv[argnum]) == 0)
{
// 動作モードログファイル別出力モード(1)にする
gvcd_mode = 01;
}
// 引数の中にログファイル別出力指定があるなら
if (strcasecmp("log=disp", argv[argnum]) == 0)
{
// 動作モードログファイル画面出力モード(2)にする
gvcd_mode = 2;
}
// 引数の中にダンプモード指定があるなら
if (strcasecmp("mode=dump", argv[argnum]) == 0)
{
// 動作モードをダンプモード(99)にする
gvcd_mode = 99;
}
}
// 通常モード(ログはSYSLOG出力)なら
if (gvcd_mode == 0)
{
// ----------------
// SYSLOGへの接続
// ----------------
openlog("gvcd", LOG_PID, LOG_DAEMON);
}
// ログファイル別出力モードなら
else if (gvcd_mode == 1)
{
// ログファイルを開く
gvc_log_fp = open(GVC_LOG_FILENAME, O_CREAT | O_APPEND | O_RDWR, 0755);
// ログファイルが開けなかったら
if (gvc_log_fp == -1)
{
// 最後のシステムエラーを表示
perror(GVC_LOG_FILENAME);
// 終わり
exit(3);
}
}
// 通常モードか、ログファイル別出力モードなら
if ((gvcd_mode == 0) || (gvcd_mode == 1))
{
// ----------------
// 子プロセス作成
// ----------------
switch (fork())
{
case 0 : // 子プロセスは処理続行
/// デバッグ用
// LOGメッセージ設定
/// sprintf(logstr, "Child Process is continue.");
// ログにメッセージを出力
/// put_log(gvcd_mode, logstr);
break;
case -1 : // fork関数異常終了
/// デバッグ用
// LOGメッセージ設定
/// sprintf(logstr, "fork() error!?");
// ログにメッセージを出力
/// put_log(gvcd_mode, logstr);
return -1;
default : // 親プロセスは終了する
/// デバッグ用
// LOGメッセージ設定
/// sprintf(logstr, "Parent Process is end.");
// ログにメッセージを出力
/// put_log(gvcd_mode, logstr);
// 終わり
exit(0);
}
// ----------------
// PIDファイルをチェック
// ----------------
// PIDファイルがないなら
if (stat(GVC_PID_FILENAME, &pidstat) == -1)
{
// PIDファイルを新規に開く
pidfile = fopen(GVC_PID_FILENAME, "w");
// 開けなかったら
if (pidfile == NULL)
{
// LOGメッセージ設定
sprintf(logstr, "Could not open pid file : %s", GVC_PID_FILENAME);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
// 終わり
exit(EXIT_FAILURE);
}
// 開けたなら
else
{
/// デバッグ用
// LOGメッセージ設定
/// sprintf(logstr, "Started Grobal Versatile Controler daemon");
// ログにメッセージを出力
/// put_log(gvcd_mode, logstr);
}
}
// PIDファイルがあるなら
else
{
// LOGメッセージ設定
sprintf(logstr, "Found a pid file : %s", GVC_PID_FILENAME);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
// 終わり
exit(EXIT_FAILURE);
}
// 新しいセッション作成、が失敗したなら
if (setsid() < 0)
{
// LOGメッセージ設定
sprintf(logstr, "setsid error");
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
// 終わり
exit(EXIT_FAILURE);
}
else
{
/// デバッグ用
// LOGメッセージ設定
/// sprintf(logstr, "setsid OK");
// ログにメッセージを出力
/// put_log(gvcd_mode, logstr);
}
// カレントディレクトリをトップに移動
if (chdir("/") < 0)
{
// LOGメッセージ設定
sprintf(logstr, "chdir / error");
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
// 終わり
exit(EXIT_FAILURE);
}
else
{
/// デバッグ用
// LOGメッセージ設定
/// sprintf(logstr, "chdir / OK");
// ログにメッセージを出力
/// put_log(gvcd_mode, logstr);
}
// umask をリセット
umask(0);
// PIDファイルに現在のPIDを出力
fprintf(pidfile, "%ld\n", (long) getpid());
fclose(pidfile);
// stdin, stdout, stderrを閉じる
int fd = 0;
int fdlimit = sysconf(_SC_OPEN_MAX);
while (fd < fdlimit)
{
close(fd++);
}
}
// ----------------
// 初期処理
// ----------------
// 受信バッファをクリア
memset(rx_buffer, 0, BUFF_SIZE);
/// デバッグ用
// LOGメッセージ設定
/// sprintf(logstr, "Device:%s Open!", argv[1] );
// ログにメッセージを出力
/// put_log(gvcd_mode, logstr);
// デバイス(シリアルポート)オープン:読み書き用、TTY制御せず
/// gvc_port = open(argv[1], O_RDWR);
gvc_port = open(argv[1], O_RDWR | O_NOCTTY);
// デバイスが開けなかったら
if(gvc_port < 0)
{
// 最後のシステムエラーを表示
perror(argv[1]);
// 終わり
exit(2);
}
// OKなら、シリアルポートを初期化
serial_reset(gvc_port);
// ----------------
// GVCキュー処理テーブルの初期化処理(戻り値:int、メッセージそのものは(void *)に型キャストして渡す(メッセージの中身はそれぞれ異なるため)
// ----------------
for( func_num = 0; func_num <= 0xff; func_num++ )
{
// GVCメッセージ処理テーブルにダミー処理を入れる
gvc_queue_job[func_num] = &gvc_q_job_dummy;
}
// ----------------
// GVCメッセージ処理テーブルの初期化処理(戻り値:int、メッセージそのものは(void *)に型キャストして渡す(メッセージの中身はそれぞれ異なるため)
// ----------------
for( func_num = 0; func_num <= 0xff; func_num++ )
{
// GVCメッセージ処理テーブルにダミー処理を入れる
gvc_msg_job[func_num] = &gvc_msg_job_dummy;
}
// ------------------------------
// 個別にキュー処理関数のポインタを設定
// ------------------------------
gvc_queue_job[0x01] = &gvc_q_job_version;
gvc_queue_job[0x02] = &gvc_q_job_modulelist;
gvc_queue_job[0x03] = &gvc_q_job_moduledata;
gvc_queue_job[0x20] = &gvc_q_job_switchoff;
gvc_queue_job[0x21] = &gvc_q_job_switchon;
gvc_queue_job[0x2f] = &gvc_q_job_switchstatus;
gvc_queue_job[0x91] = &gvc_q_job_irtx;
gvc_queue_job[0x92] = &gvc_q_job_irrx;
gvc_queue_job[0x93] = &gvc_q_job_irset;
gvc_queue_job[0x94] = &gvc_q_job_irget;
gvc_queue_job[0x95] = &gvc_q_job_irdel;
gvc_queue_job[0x7e] = &gvc_q_job_masterreset;
gvc_queue_job[0x7f] = &gvc_q_job_masterstop;
gvc_queue_job[0xff] = &gvc_q_job_daemonstop;
// ------------------------------
// 個別にメッセージ処理関数のポインタを設定
// ------------------------------
gvc_msg_job[GVC_MSG_DELIMITER] = &gvc_msg_job_delimiterframe;
gvc_msg_job[GVC_MSG_OTHER] = &gvc_msg_job_other;
gvc_msg_job[GVC_MSG_DIST] = &gvc_msg_job_distance;
gvc_msg_job[GVC_MSG_HUMI] = &gvc_msg_job_humidity;
gvc_msg_job[GVC_MSG_IR] = &gvc_msg_job_ir;
gvc_msg_job[GVC_MSG_TEMP] = &gvc_msg_job_temperature;
gvc_msg_job[GVC_MSG_LIGHT] = &gvc_msg_job_light;
gvc_msg_job[GVC_MSG_PRESS] = &gvc_msg_job_pressure;
// メッセージキューのメッセージの長さを設定
msgq_length = sizeof(GVC_MESSAGE_QUEUE_t) - sizeof(unsigned long);
// パス名とプロジェクト識別子を System V IPC キーに変換する(命令キュー)
// gvcdが動いていることが前提なので、gvcdのPIDファイルから生成すればOK。
msgq_key = ftok(GVC_PID_FILENAME, 'w');
// メッセージキューを作成(新規作成だが、既存だった場合にはエラー…にした方がいいのか、どうなのか?
// message_qid = msgget(msgq_key, IPC_CREAT | IPC_EXCL | 0660);
// コマンド(gvc_cmd系)の実行を誰でもできるようにするなら0666とすること)
message_qid = msgget(msgq_key, IPC_CREAT | 0666);
// メッセージキューが作成できたなら(message_qid!=-1)
if (message_qid != -1)
{
/// デバッグ用
// LOGメッセージ設定
/// sprintf(logstr, "QID = %d, msgq_length=%d", message_qid, msgq_length);
// ログにメッセージを出力
/// put_log(gvcd_mode, logstr);
}
// メッセージキューが作成できなかったら(message_qid=-1)
else
{
// LOGメッセージ設定
sprintf(logstr, "Message Queue make error : %s", strerror(errno));
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
// 終わり
exit(EXIT_FAILURE);
}
//メッセージキューのメッセージ部分を初期化
memset((void *)&rcv_message_queue.q, msgq_length, 0x00);
// データ格納フラグ初期化
datafp_flag = 0;
// ------------------------------
// メインの無限ループ
// ------------------------------
// 受信バッファを初期化
memset((void *)rx_buffer, 0x00, BUFF_SIZE);
// 受信バッファにGVC_SERIAL_MESSAGE_tをかぶせる
gvc_serial_message = (GVC_SERIAL_MESSAGE_t *)rx_buffer;
// 起動メッセージを受信データに設定
gvc_serial_message->msg_type = GVC_MSG_OTHER; // メッセージタイプを設定
gvc_serial_message->dev_num = 0xFF; // デバイス番号を設定
gvc_serial_message->format = 0x01; // フォーマットを設定(0x01=通常テキスト)
gvc_serial_message->cmd = 0x01; // 結果(情報種別)を設定(0x01=初期情報、システム情報)
sprintf((char *)gvc_serial_message->data, "%s Ver.%s Start (_IO_BUFSIZ=%d)", SOFTNAME, VERSION, _IO_BUFSIZ); // データを設定
gvc_serial_message->data_len = strlen((char *)gvc_serial_message->data); // データ長を設定
// CRCを計算して、メッセージの最後に設定
gvc_serial_message->data[ gvc_serial_message->data_len ] = GetCRC8((void *)gvc_serial_message, GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_serial_message->data_len);
// ↑データを送信する側は、データのCRCを計算したあとで
// そのCRCをデータの最後に連結して相手に送ればいい
// 受信バッファにデータを格納する位置を設定
rx_pos = GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_serial_message->data_len + 1;
// 受信バッファの長さを設定
rx_buffer_len = rx_pos;
while(1)
{
// GVCコマンド送信可能状態(=1)なら
while(gvc_cmd_ready)
{
// メッセージ受信…ここではgvcdに対しての命令を送信している
// 「求めているメッセージがない」こともある.msgflgとしてIPC_NOWAITが指定されてい
// る場合にはすぐにエラーを返すが,そうでない場合には求めるメッセージが得られるか,
// キューが消えるか,シグナルで捕獲されるまで待つ.
msgq_result = msgrcv(message_qid, &rcv_message_queue, msgq_length, COMMAND_Q, IPC_NOWAIT);
// メッセージが受信できたなら(!=-1)
if (msgq_result != -1)
{
// ここで本来は受信したキューメッセージのCRCのチェックをしたいが…
// メッセージキュー、というかLinuxレベルになるとテーブル構造体のアラインメントが行われるから実質できない。
// 時間を取得(グローバル変数に格納)
get_daytime(daytime_str);
// キューに基づいて処理
gvc_queue_job[ rcv_message_queue.q.cmd ]( (void *)&rcv_message_queue );
// もしENDコマンドがきていたら
if (rcv_message_queue.q.cmd == 0xff)
{
// 終了する
goto END_JOB;
}
}
// メッセージが受信できなかったら(=-1)
else
{
// メッセージがない、ではなかったら
if (errno != ENOMSG)
{
// LOGメッセージ設定
sprintf(logstr, "QUEUE ERROR : %s", strerror(errno));
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
// 終了する
goto END_JOB;
}
// 特にメッセージがないなら
else
{
// メッセージキュー受信から抜ける
break;
}
}
}
// GVCコマンド送信可能状態をデリミタ待ち(=0)に設定
gvc_cmd_ready = 0;
// 受信待ちタイムアウト時間を設定 (1秒まつ)
tv.tv_sec = 1;
tv.tv_usec = 0;
// ファイルディスクリプタをいったん初期化(0リセット)
FD_ZERO(&fds );
// ファイルディスクリプタを設定
FD_SET(gvc_port, &fds);
// 何かデータが来たか、もしくはタイムアウトなら
if (select(gvc_port + 1, &fds, NULL, NULL, &tv) > 0)
{
// シリアルポートからデータを受信バッファに取得
rx_len = read(gvc_port, rx_buffer + rx_pos, BUFF_SIZE);
// 読み出しエラーなら
if (rx_len < 0)
{
// もし割り込みによる中断だったら
if (errno == EINTR)
{
// LOGメッセージ設定
sprintf(logstr, "READ is EINTR. rx_len=%d, errno=%d", rx_len, errno);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
// それ以外の場合には
else
{
// LOGメッセージ設定
sprintf(logstr, "READ is OTHER ERROR !? rx_len=%d, errno=%d", rx_len, errno);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
// 終了する
goto END_JOB;
}
}
// 読み出しサイズがなかった場合には
else if (rx_len == 0)
{
// LOGメッセージ設定
sprintf(logstr, "READ is ZERO !? rx_len=%d, errno=%d", rx_len, errno);
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
// 受信しなおし
continue;
}
// 正常に読めたときには
else
{
// 次の受信位置を設定
rx_pos += rx_len;
// 受信バッファ長を設定
rx_buffer_len += rx_len;
}
}
// マスターコントローラーからのメッセージ待ち
// rx_buffer_lenが最小メッセージサイズ以上の(5倍くらいの)長さがあるなら、解析処理をする
if (rx_buffer_len >= GVC_MIN_MESSAGE_LENGTH)
{
// 0からrx_len-GVC_MIN_MESSAGE_LENGTHの中に有効なメッセージタイプがあるかどうかスキャン
for (check_char = 0; check_char <= (rx_buffer_len - GVC_MIN_MESSAGE_LENGTH); check_char ++)
{
// 0xaaが合ったら、
if (rx_buffer[check_char] == 0xaa)
{
// rx_buffer_lenがcheck_char+DELIMITER_LENGTH+1以上あるなら
if (rx_buffer_len >= check_char + (DELIMITER_LENGTH + 1))
{
// そこから16バイト比較してデリミタメッセージであり、かつCRCチェックもOKなら
if (memcmp(rx_buffer + check_char, (void *)GVC_DELIMITER_MSG, DELIMITER_LENGTH) == 0 &&
GetCRC8((void *)(rx_buffer + check_char), (DELIMITER_LENGTH + 1)) == 0 )
{
// 時間を取得(グローバル変数に格納)
get_daytime(daytime_str);
// メッセージに基づいて処理
gvc_msg_job_delimiterframe((void *)rx_buffer + check_char);
// あまったデータの先頭位置を設定
rx_remainder = check_char + (DELIMITER_LENGTH + 1);
// あまったデータを計算
rx_remainder_len = rx_buffer_len - rx_remainder;
// あまったデータがないなら
if (rx_remainder_len == 0)
{
// 次の受信バッファポインタを設定
rx_pos = 0;
// 受信バッファ長を設定
rx_buffer_len = 0;
}
// あまったデータがあるなら
else
{
// メッセージの次から残りのデータを受信バッファの先頭にコピー
memmove(rx_buffer, rx_buffer + rx_remainder, rx_remainder_len);
// 次の受信バッファポインタを設定
rx_pos = rx_remainder_len;
// 受信バッファ長を設定
rx_buffer_len = rx_remainder_len;
}
// スキャンループから抜ける
break;
}
}
}
// 有効なメッセージタイプがあったら、
else if (gvc_msg_job[ rx_buffer[check_char] ] != &gvc_msg_job_dummy)
{
// 受信バッファにGVC_SERIAL_MESSAGE_tをかぶせる
gvc_serial_message = (GVC_SERIAL_MESSAGE_t *)(rx_buffer + check_char);
// 受信バッファ内にCRCまで含めたメッセージフレームが収まっているなら
if ( rx_buffer_len >= check_char + (GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_serial_message->data_len + 1) )
{
// CRCチェックしてOKなら
if ( GetCRC8((void *)gvc_serial_message, (GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_serial_message->data_len + 1)) == 0 )
{
// 時間を取得(グローバル変数に格納)
get_daytime(daytime_str);
// メッセージに基づいて処理
gvc_msg_job[ gvc_serial_message->msg_type ]( (void *)gvc_serial_message );
// あまったデータの先頭位置を設定
rx_remainder = check_char + (GVC_SERIAL_MESSAGE_HEADER_SIZE + gvc_serial_message->data_len + 1);
// あまったデータを計算
rx_remainder_len = rx_buffer_len - rx_remainder;
// あまったデータがないなら
if (rx_remainder_len == 0)
{
// 次の受信バッファポインタを設定
rx_pos = 0;
// 受信バッファ長を設定
rx_buffer_len = 0;
}
// あまったデータがあるなら
else
{
// メッセージの次から残りのデータを受信バッファの先頭にコピー
memmove(rx_buffer, rx_buffer + rx_remainder, rx_remainder_len);
// 次の受信バッファポインタを設定
rx_pos = rx_remainder_len;
// 受信バッファ長を設定
rx_buffer_len = rx_remainder_len;
}
// スキャンループから抜ける
break;
}
}
}
else
{
}
}
}
}
// 終了する場合にここに飛ぶ
END_JOB:
// ポートを閉じる
close(gvc_port);
// 通常モードか、ログファイル別出力モードなら
if ((gvcd_mode == 0) || (gvcd_mode == 1))
{
// PIDファイルを削除
unlink(GVC_PID_FILENAME);
// LOGメッセージ設定
sprintf(logstr, "DELETED PID FILE");
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
}
// メッセージキューを破棄
msgctl(message_qid, IPC_RMID, 0);
// LOGメッセージ設定
sprintf(logstr, "MESSAGE QUEUE DELETED");
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
// LOGメッセージ設定
sprintf(logstr, "GVCD END. Thank you! :-)");
// ログにメッセージを出力
put_log(gvcd_mode, logstr);
// 終わり
return 0;
}